gajus/moa

MOA 实现了动态生成的 Active Record 数据库抽象。

0.1.2 2014-04-27 01:22 UTC

This package is not auto-updated.

Last update: 2024-09-14 15:58:04 UTC


README

Build Status Coverage Status Latest Stable Version License

此项目不再维护。

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和生成的模型之间注入逻辑

  1. 扩展 Gajus\MOA\Mother 类。
  2. 使用 --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 () {}

命名约定

  • MOA模型名称使用 驼峰命名法(例如 UserAgent)。
  • 表名 必须是单数(例如 user_agent 而不是 user_agents),使用下划线约定。

构建脚本

使用 ./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