harp-orm/harp

轻量级且灵活的ORM,无魔法

0.3.2 2014-08-28 08:49 UTC

This package is auto-updated.

Last update: 2024-09-21 20:59:09 UTC


README

Harp ORM

Build Status Scrutinizer Quality Score Code Coverage Latest Stable Version

Harp ORM 是一个轻量级的 PHP 对象持久层 DataMapper。

快速示例

// Model Class
use Harp\Harp\AbstractModel;

class UserModel extends AbstractModel
{
    public static function initialize($config)
    {
        $config
            ->addRel(new Rel\BelongsTo('address', $config, Address::getRepo()));
    }

    public $id;
    public $name;
    public $email;
    public $addressId;

    public function getAddress()
    {
        return $this->get('address');
    }

    public function setAddress(Address $address)
    {
        return $this->set('address', $address);
    }
}

// Saving new model
$user = new UserModel(['name' => 'my name']);
UserRepo::save($user);

// Loading model
$loadedUser = UserRepo::find(1);
var_dump($loadedUser);

// Loading related model
$address = $loadedUser->getAddress();
var_dump($loadedUser->getAddress());

为什么?

为什么还需要另一个ORM?目前没有ORM使用最新的PHP特性。PHP语言本身的近期进步(例如 traits),以及外部静态分析工具,使得编写易于验证为正确的应用程序成为可能,然而大多数现有的ORM都没有使用它们,这使得静态代码分析不太有用。最后,这个包旨在更接近底层,智能地使用现有的PHP类和扩展来使您的模型快速,而不牺牲功能。这里是简要介绍:

  • 尽可能使用 harp-orm/query 和 PDO,从而大大提高性能。它具有一些当前ORM没有的非常有用的功能。
  • 完全支持 多态 - 既有“属于多态”又有“单表继承”
  • 正确的 软删除,代码的每个部分都知道
  • 延迟加载预加载,适用于多态关系
  • 使用 分组查询 保存多个模型,以增加性能
  • 不强制文件夹结构,将您的类放置在任何地方
  • 使用 PSR编码风格symfony命名约定,使代码库更干净、更易于阅读
  • 使用单个命令保存所有关联模型,底层使用 查询分组
  • 完全可扩展的接口。使用原生PHP5构造来允许使用 traits 和接口进行 扩展
  • 所有方法都有 正确的docblocks,以便对基于此构建的代码进行更准确的静态代码分析。

安装

Harp 使用 composer,所以安装就像这样简单

composer require harp-orm/harp:~0.3.0

它使用 harp-orm/query 连接到数据库,因此您还需要配置连接

use Harp\Query\DB;

DB::setConfig([
    'dsn' => 'mysql:dbname=harp-orm/harp;host=127.0.0.1',
    'username' => 'root',
    'password' => 'root',
]);

子部分

定义模型

以下是一个示例模型类。

use Harp\Harp\AbstractModel;

class User extends AbstractModel
{
    // Configure the "Repo" object for this model class
    // This holds all the database-specific configs,
    // as well as relations with other models
    public static function initialize($config)
    {
        $config

            // Configure relations
            ->addRel(new Rel\BelongsTo('address', $config, AddressRepo::get()));

            // Configure validations
            ->addAssert(new Assert\Present('name'))
            ->addAssert(new Assert\Email('name'));
    }

    // Public properties persisted as columns in the table
    public $id;
    public $name;
    public $email;
    public $addressId;
}

所有公共属性都持久化到数据库中,如果可用,则使用原生类型。

提示 一旦加载了相关对象,它们将被缓存并在后续请求中返回,然而数据不会保留在模型本身中,因此如果您对一个模型进行 var_dump,它将仅返回模型本身的数据,并保持堆栈跟踪的清晰。

所有配置方法的详细列表

有关事件的更多信息,请参阅 使用事件进行扩展

从数据库检索

从数据库中检索模型(以及保存,但稍后再说)是通过模型类上的静态方法处理的。要按主键查找模型,请使用 find 方法。

$user1 = User::find(8);
$user2 = User::find(23);

如果模型有一个“name”属性(或配置了nameKey),则可以使用 findByName 方法。

$user1 = User::findByName('Tom');
$user2 = User::findByName('John');

对于更复杂的检索,可以使用 findAll 方法,它返回一个 'Find' 对象。它具有构建SQL查询的方法的丰富接口

$select = User::findAll();
$select
    ->where('name', 'John')
    ->whereIn('type', [1, 4])
    ->joinRels(['address' => 'city'])
    ->limit(10);

$users = $select->load();

foreach ($users as $user) {
    var_dump($user);
}

从数据库检索的所有模型都存储在“身份映射”中。因此,如果在以后的时间,再次加载相同的模型。它将返回相同的PHP对象,与数据库行相关联。

$user1 = User::find(10);
$user2 = User::find(10);

// Will return true
echo $user1 === $user2;

详细 findAll 的文档

持久化模型

当模型被创建、修改或删除后,通常需要再次持久化。这可以通过模型上的 "save" 方法完成。

$user = User::find(10);
$user->name = 'new name';

$address = new Address(['location' => 'home']);
$user->setAddress($address);

// This will save the user, the address and the link between them.
User::save($user);

$user2 = User::find(20);
$user2->delete();

// This will remove the deleted user from the database.
User::save($user2);

当你添加/删除或以其他方式修改相关模型时,它们将与你的主要模型一起保存。

保留多个模型

你可以使用 saveArray 方法一次性保留同一仓库中的多个模型(使用查询分组)。只需传递一个模型数组。

$save = User::saveArray([$user1, $user2, $user3]);

软删除

如果你需要在删除模型后仍将其保留在数据库中,例如逻辑删除,可以使用 SoftDeleteTrait

// Model File
use Harp\Harp\AbstractModel;
use Harp\Harp\Model\SoftDeleteTrait;

class Order extends AbstractModel
{
    use SoftDeleteTrait;

    public static function initialize($config)
    {
        // The trait has its own initialize method that you'll have to call
        SoftDeleteTrait::initialize($config);
    }
}

$order = Order::find(2);

$order->delete();

// This will issue an UPDATE instaead of a DELETE, marking this row as "deleted".
Order::save($order);

$order = Order::find(2);

// This will return true
echo $order->isVoid();

这将在你的模型上添加一些方法。关于软删除的详细信息请在此处阅读

继承

有时你需要多个模型共享同一个数据库表 - 例如,如果同一功能只有细微的差别。这被称为单表继承。

Harp ORM 支持开箱即用的模型继承。关于继承的详细信息请在此处阅读

模型状态

在整个生命周期中,模型有不同的状态(Harp\Harp\Model\State)。它们可以是

有几种方法可以处理模型状态

脏跟踪

模型跟踪其公共属性的所有更改,以最小化对数据库的更新。你可以通过调用这些方法来使用该功能

示例

$user = User::find(10);

// returns false
echo $user->isChanged();

$user->name = 'new test';

// returns true
$user->isChanged();

// returns true
$user->hasChange('name');

// returns ['name' => 'new test']
$user->getChanges();

// returns original name
$user->getOriginal('name');

$user->resetOriginal();

// returns 'new test'
$user->getOriginal('name');

扩展

当你想编写扩展 Harp ORM 功能的包,或者简单地在不同模型之间共享代码时,你可以使用 PHP 的原生 Traits。它们允许你静态地扩展类。Harp ORM 的所有内部结构都是围绕允许你轻松完成此操作构建的,这是编写 "行为" 或 "模板" 的首选方式。

除此之外,你还将能够为模型生命周期的各种事件添加事件监听器。

关于扩展的详细信息请在此处阅读

直接数据库访问。

有时你需要直接接触底层并编写自定义 SQL。为了帮助你这样做,你可以直接使用内部查询类。

$update = User::insertAll()
    ->columns(['name', 'id'])
    ->select(
        Profile::selectAll()
            ->clearColumns()
            ->column('name')
            ->column('id')
            ->where('name', 'LIKE', '%test')
    );

// INSERT INTO User (name, id) SELECT name, id FROM Profile WHERE name LIKE '%test'
$update->execute();

关于自定义查询的更多细节,请参阅查询部分

许可协议

版权所有 (c) 2014, Clippings Ltd. 由 Ivan Kerin 在clippings.com开发

在 BSD-3-Clause 许可协议下,请阅读 LICENSE 文件。

图标由 Freepik 制作,来源于 www.flaticon.com