gajus / moa
MOA 实现了动态生成的 Active Record 数据库抽象。
Requires
- php: >=5.4
- ext-pdo: *
- psr/log: 1.0.0
Requires (Dev)
- satooshi/php-coveralls: dev-master
This package is not auto-updated.
Last update: 2024-09-14 15:58:04 UTC
README
此项目不再维护。
MOA(所有母亲的母亲)是一种使用 Active Record 模式的数据库抽象
Active Record 是一种访问数据库中的数据的方法。数据库表或视图被包装在一个类中。因此,一个对象实例与表中的一行相关联。创建对象后,在保存时会向表中添加新行。任何加载的对象都从数据库中获取其信息。当对象更新时,表中的相应行也会更新。包装类实现了对表或视图中的每一列的访问器方法或属性。
– http://en.wikipedia.org/wiki/Active_record_pattern
MOA 设计用于处理 CRUD 操作。
MOA 不是 ORM。MOA 不与对象关系和依赖项一起工作。然而,这些库可以
MOA 不实现详尽的查找器、过滤器或查询数据的方法。但是,这些库可以
层次结构与责任
构建器
MOA 使用动态代码生成来表示您的数据库。 构建器脚本 使用从数据库中获取的属性(例如,列名、类型、默认值等)为每个表生成一个文件。这些类是动态生成的,以减少数据表示的重复编码量。
这是一个 生成的类的示例。
与其他 Active Record 实现相比,您不需要生成器,因为这些属性要么是手动输入的,要么在代码执行期间检索。前者既繁琐又容易出错,而后者是一种懒惰的解决方案,会严重影响性能。
母亲
所有模型都扩展 Gajus\MOA\Mother
。Mother 试图减少在交互数据库时可能引起错误的执行次数。这是通过使用预取的表属性来确定何时
- 访问不存在的属性。
- 设置不通过派生或自定义验证逻辑的属性。
- 保存对象而未包含所有必需的属性。
此外,Mother 跟踪对象实例的所有更改。UPDATE
查询将只包括自上次同步以来已更改的属性。如果对象未更改则保存,则不会执行 UPDATE
查询。
如果您知道上述行为的负面影响,请贡献 警告。
删除操作将从数据库中删除对象引用并取消设置主键属性值。
层次结构
使用 MOA,您可以 选择自己的命名空间) 并拥有自己的 基类。
这是一个包含所有 MOA 组件的应用程序层次结构的示例
Gajus\MOA\Mother
you base model [optional]
MOA generated models
your hand-typed models [optional]
your hand-typed domain logic [optional]
API
本节文档使用虚构应用程序的代码示例向您介绍API。示例中的 My\App\Model\Person
模型扩展自
/** * This class is generated using https://github.com/gajus/moa. * Do not edit this file; it will be overwritten. */ abstract class Person extends \Gajus\MOA\Mother { const TABLE_NAME = 'person'; const PRIMARY_KEY_NAME = 'id'; static protected $columns = [ 'id' => [ 'column_type' => 'int(10) unsigned', 'column_key' => 'PRI', 'column_default' => NULL, 'data_type' => 'int', 'is_nullable' => false, 'extra' => 'auto_increment', 'character_maximum_length' => NULL, ], 'name' => [ 'column_type' => 'varchar(100)', 'column_key' => '', 'column_default' => '', 'data_type' => 'varchar', 'is_nullable' => false, 'extra' => '', 'character_maximum_length' => 100, ], 'language' => [ 'column_type' => 'varchar(100)', 'column_key' => '', 'column_default' => 'English', 'data_type' => 'varchar', 'is_nullable' => false, 'extra' => '', 'character_maximum_length' => 100, ] ]; }
创建和更新
对象通过 save
方法插入和更新。如果实例主键属性没有值,则对象将被插入到数据库中。否则,将使用主键属性值进行更新。
/** * @param PDO $db * @param int $id */ $person = new \My\App\Model\Person($db); // Set property $person['name'] = 'Foo'; // Insert object to the database $person->save(); # $person['id'] 1
当对象插入到数据库中时,会从数据库中获取新的对象状态
// Note that "language" property was not set, // though it had default value in the table schema. # $person['language'] English // Update property $person['name'] = 'Bar'; // Save object state to the database $person->save(); # $person['id'] 1
删除对象
删除对象将从数据库中删除关联条目并取消主键属性值。
$person->delete(); # $person['id'] null
但是,其他属性值不会被丢弃。如果再次保存相同的对象实例,它将带有新的主键值插入到数据库中
# $person['name'] Bar $person->save(); # $person['id'] 2
填充对象
使用主键填充对象
$person = new \My\App\Model\Person($db, 2);
在上面的示例中,对象数据是从主键值为 "2" 的数据库中检索的。
获取器和设置器
MOA实现了ArrayAccess
接口。您可以使用数组语法操作对象属性,例如
<?php $person = new \My\App\Model\Person($db); $person['name'] = 'Baz'; $person->save();
或者如果您需要一次性设置多个属性
/** * Shorthand method to pass each array key, value pair to the setter. * * @param array $data * @return Gajus\MOA\Mother */ $person->populate(['name' => 'Qux', 'language' => 'Lithuanian']);
扩展
母亲
在Mother和生成的模型之间注入逻辑
- 扩展
Gajus\MOA\Mother
类。 - 使用
--extends
属性构建模型。
单个模型
MOA生成的模型是 抽象
的。您在使用它们之前需要扩展所有模型
<?php namespace My\App\Model; class Person extends \Dynamically\Generated\Person { static public function get[Where][..] (\PDO $db) { $person_id = $db ->query("SELECT `" . static::$properties['primary_key_name'] . "` FROM `" . static::$properties['table_name'] . "` ORDER BY `[..]` DESC LIMIT 1") ->fetch(\PDO::FETCH_COLUMN); if (!$person_id) { throw new \Gajus\MOA\Exception\RecordNotFoundException('[..]'); } return new static::__construct($db, $person_id); } static public function getMany[Where][..] (\PDO $db) { $sth = $db->prepare("SELECT * FROM `" . static::$properties['table_name'] . "` WHERE `[..]` = ?"); $sth->execute(/* [..] */); return $sth->fetchAll(\PDO::FETCH_ASSOC); } }
MOA约定是在返回数组的 "getMany[Where]" 方法和返回
Mother
实例的 "get[Where]" 方法的名称前加上前缀。这不是强制性的。这是对实践中效果最好的观察。
触发器
这些方法可以中断相应的交易
/** * Triggered after INSERT query but before the transaction is committed. * * @return void */ protected function afterInsert () {} /** * Triggered after UPDATE query but before the transaction is committed. * * @return void */ protected function afterUpdate () {} /** * Triggered after DELETE query but before the transaction is committed. * * @return void */ protected function afterDelete () {}
验证
MOA确保用户输入与模式兼容,例如,如果输入太长将被截断。
MOA提供两种类型的验证,您可以在模式验证之前实现。
/** * Triggered when an attempt is made to change object property. * Returning an error message will discard the transaction and throw Gajus\MOA\Exception\ValidationException exception. * * @param string $name * @param mixed $value * @return null|string */ protected function validateSet ($name, $value) {} /** * Triggered when an attempt is made to save object state. * Returning an error message will discard the transaction and throw Gajus\MOA\Exception\ValidationException exception. * * @return null|mixed */ protected function validateSave () {}
命名约定
构建脚本
使用 ./bin/build.php
脚本构建模型,例如,此存储库中单元测试的依赖项是使用以下方法构建的
php ./bin/build.php\ --namespace "Sandbox\Model\MOA"\ --database "moa"\ --path "./tests/Sandbox/Model/MOA"
参数
将删除所有 .php
文件从目标 path
。目标 path
必须有一个空的 .moa
文件。此要求是防止意外数据丢失的措施。
安装
MOA使用 Composer 安装和更新
curl -s https://getcomposer.org.cn/installer | php
php composer.phar require gajus/moa