movim/modl

此包已被废弃,不再维护。未建议替代包。

使用DAO模式的轻量级PHP数据库层

dev-master 2018-03-11 11:19 UTC

This package is not auto-updated.

Last update: 2020-01-22 18:00:40 UTC


README

Modl代表Movim数据层。它是连接Movim核心代码与SQL数据库的库。

Modl采用AGPLv3许可证。

特性

Modl旨在提供一个轻量级且易于调整的库,以及通过手动编写来优化SQL请求的可能性。

所有SQL请求都必须符合规范,以便在各个数据库上返回相同的结果。然后,Modl将解释这些结果并以对象的形式返回它们。

Modl目前支持MySQL和PostGreSQL数据库。

集成到您的项目中

此库符合PSR-0PSR-4规范,因此可以通过自动加载器轻松加载。您有两种方式来完成此操作:通过Composer和使用内部加载器。

通过Composer

只需将其添加到您的项目的composer.json文件中。您可以在Packagist上找到movim/modl包

以下是一个示例,展示了如何将库集成到“composer.json”文件中。

{
    "require": {
        "movim/modl": "dev-master"
    }
}

通过内部加载器

Modl还有一个内部加载器。

require 'modl/src/Modl/Loader.php';
\Modl\Loader::register();

初始化

一旦库加载到您的项目中,您就可以在任何地方实例化它。

下面的代码来自Movim项目的bootstrap.php文件。

$db = Modl\Modl::getInstance();
$db->setModelsPath(APP_PATH.'models');

Modl\Utils::loadModel('Presence');
Modl\Utils::loadModel('Contact');


$db->setConnectionArray(Conf::getServerConf());
$db->connect();

创建一个将包含所有数据模型的目录。然后,可以将有用的数据模型加载到Modl中使用。

setConnectionArray()方法的参数是一个PHP数组,具有以下结构。

$conf = [
  'type' => 'mysql', // or 'pgsql' for a PostGreSQL database
  'username' => 'username', // the user of the database
  'password' => 'password', // the users's password
  'host' => 'localhost', // the host of the database
  'port' => '3306', // the port
  'database' => 'movim' // the name of the database
];

如何编写模型

让我们以创建一个“Item”模型(这是Movim中现有的模型,可以在这里找到)为例。

为此,您需要在模型目录中创建一个新的目录(在加载库之前定义)。然后,在此新目录中创建两个文件。

  • Item.php,它将是模型的主类。每个实例都将对应于数据库返回的一个元组。
  • ItemDAO.php,它将包含所有与此模型相关的请求。

Item.php

namespace Modl;

class Item extends Model
{
    public $server;
    public $jid;
    public $name;
    public $node;
    public $updated;
    public $hash;

    public $_struct = [
        'server'    => ['type' => 'string','size' => 64,'key' => true],
        'jid'       => ['type' => 'string','size' => 64,'key' => true],
        'node'      => ['type' => 'string','size' => 96,'key' => true],
        'name'      => ['type' => 'string','size' => 128],
        'updated'   => ['type' => 'date','mandatory' => true],
        'hash'      => ['type' => 'string','size' => 64]
    ];

    public $_uniques = [
        ['server', 'jid'],
        ['hash']
    ];
}

上面的代码很容易理解。Item从Modl\Model继承。数据库中创建的表的每一列都将转换为类的属性。

在构造函数中,必须定义从Modl\Model继承的_struct属性,以包含其他属性的特定信息。

Modl目前支持六种类型的数据

  • 字符串用于名称、键等
  • 日期用于显然的日期
  • 整型用于使用整数
  • 文本用于存储长字符串或大二进制值
  • 布尔值用于使用布尔值
  • 序列化用于在数据库中保存和检索PHP变量

除了日期类型和布尔值类型外,可以使用“size”关键字为每种数据类型指定大小。全局上,“mandatory”和“key”关键字分别用于(1)禁止在保存属性时出现任何空值,以及(2)指定属性为表的键。如果属性被定义为键,则“mandatory”关键字将无用。

还可以使用$_uniques数组定义唯一约束。

ItemDAO.php

ItemDAO继承自Modl\SQL类。以下代码允许您将Item实例插入到数据库中。

namespace Modl;

class ItemDAO extends SQL
{
    function set(Item $item)
    {
        $this->_sql = '
            update item
            set name   = :name,
                updated = :updated
            where server = :server
                and jid  = :jid
                and node = :node';

        $this->prepare(
            'Item',
            [
                'name'   => $item->name,
                'updated'=> $item->updated,
                'server' => $item->server,
                'jid'    => $item->jid,
                'node'   => $item->node
            ]
        );

        $this->run('Item');

        if(!$this->_effective) {
            $this->_sql = '
                insert into item
                (server,
                node,
                jid,
                name,
                updated
                )
                values(
                    :server,
                    :node,
                    :jid,
                    :name,
                    :updated
                    )';

            $this->prepare(
                'Item',
                [
                    'name'   => $item->name,
                    'updated'=> $item->updated,
                    'server' => $item->server,
                    'jid'    => $item->jid,
                    'node'   => $item->node
                ]
            );

            $this->run('Item');
        }
    }
}

由于一致性考虑以及对所有SQL数据库的支持,Modl创建的表名始终为小写。您需要在您计划支持的任何数据库上测试您的请求,并确保所有DBMS返回相同的结果。

建议您在测试MySQL之前先为PostGreSQL进行开发。

准备

SQL请求由_sql定义。prepare()方法将更改请求中使用的键(始终由:前缀)关联的值,并检查和转换元素到模型构造函数中定义的JSON结构。

如果您想在请求中影响另一个模型中的值,请将模型名称前缀到参数键。

effective()方法返回一个与请求有效性相关的布尔值。在我们的例子中,它允许我们执行“插入或更新”(尝试更新表中的元组,如果不存在则插入)请求。

执行

请求的执行是通过run()方法完成的。您需要提供一个参数来指定要操作的实例类型(如果没有指定,Modl将使用与我们的DAO关联的默认对象)。如果向此方法提供一个参数,即使只有一个元组也会返回一个数组。

要获取单个实例,可以将item作为第二个参数。

return $this->run('Item', 'item');

在上述例子中,Modl将尝试将DBMS返回的数组中的每个元素转换为Item的实例。如果有多个元素具有相同的名称(例如,如果您执行了join),则仅处理第一个元素。

您也可以使用以下方式返回原始数组。

return $this->run(null, 'array');

如果您的SQL请求返回包含单个count(*)单元格,您可以直接以这种方式返回count的值。

return $this->run(null, 'count');

调用模型

加载Modl后,可以在代码中的任何位置调用定义的模型。模型是单例,这就是为什么数据库连接在整个执行过程中保持连接。

在下面的代码片段中,创建了一个新的Item实例...

$n = new \Modl\Item;
$n->server = 'movim.eu';
$n->node   = 'pink_floyd';

并将其发送到数据库。

$nd = new \Modl\ItemDAO;
$nd->set($n);

SmartDB

Modl SmartDB是Modl中新增的功能。它取代了旧表创建系统,该系统曾经在每个DAO中使用create()方法。

SmartDB不仅可以自动创建表,通过定义模型,还可以在需要修改或添加属性或模型时更新它们。

理解其工作原理非常简单。当加载Modl及其模型时,check()方法将启动SmartDB。

$md = Modl\Modl::getInstance;
$infos = $md->check();

它返回需要在数据库中进行的修改列表。通过将check()方法的参数设置为true,您授权它自行更新数据库。

$md->check(true); // Done ! Your database is up to date.