# ORM

# 前言

herosphp/orm (opens new window) 衍生于 illuminate/database (opens new window),我们对它进行了一些改造,从而适配Herosphp,大部分功能保持了相同。在这里感谢一下Laravel (opens new window)开发组,实现了如此强大好用的ORM组件。

# 安装

# 1. 安装扩展

composer require herosphp/orm

# 2. 生成配置文件database.config.php

composer vendor:publish "herosphp/orm"

# 3. 注册启动器

<?php
declare(strict_types=1);

namespace app\init;

use herosphp\annotation\Bootstrap;
use herosphp\plugin\orm\LaravelDbStarter;

#[Bootstrap(name: 'orm')]
class HerosOrmStarter extends LaravelDbStarter
{
    // 页码名称
    protected static string $pageName = 'page';

    // 自动分页
    protected static bool $autoPageResolver = false;

    //是否调试模式,true 打印执行SQL在终端
    protected static bool $debug = false;
}
HerosOrmStarter::init();

# 配置

默认配置如下,数据库支持多库配置,默认为 default

配置项 类型 默认值 备注
driver string 数据库引擎
host string 数据库地址
database string 数据库默认 DB
username string 数据库用户名
password string null 数据库密码
charset string utf8 数据库编码
collation string utf8_unicode_ci 数据库编码
prefix string '' 数据库模型前缀
options array PDO 配置
<?php

return [
    'default' => [
        'driver' =>  'mysql',
        'host' =>  'localhost',
        'port' =>  3306,
        'database' => 'test',
        'username' => 'root',
        'password' => 'root',
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix' => '',
    ],
];

有时候用户需要修改 PDO 默认配置,比如所有字段需要返回为 string。这时候就需要修改 PDO 配置项 ATTR_STRINGIFY_FETCHES 为 true。

<?php

return [
    'default' => [
        'driver' =>  'mysql',
        'host' =>  'localhost',
        'port' =>  3306,
        'database' => 'test',
        'username' => 'root',
        'password' => 'root',
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix' => '',
        'options' => [
            // 框架默认配置
            PDO::ATTR_CASE => PDO::CASE_NATURAL,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
            PDO::ATTR_STRINGIFY_FETCHES => false,
            // 如果使用的为非原生 MySQL 或云厂商提供的 DB 如从库/分析型实例等不支持 MySQL prepare 协议的, 将此项设置为 true
            PDO::ATTR_EMULATE_PREPARES => false,
        ],
    ],
];

# 多库配置

多库配置如下。

<?php

return [
    'default' => [
        'driver' =>  'mysql',
        'host' =>  'localhost',
        'port' =>  3306,
        'database' => 'demo',
        'username' => 'root',
        'password' => 'root',
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix' => '',
    ],
    'test'=>[
        'driver' =>  'mysql',
        'host' =>  'localhost',
        'port' =>  3306,
        'database' => 'test',
        'username' => 'root',
        'password' => 'root',
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix' => '',
    ],
];

使用时,只需要规定 connectiontest,就可以使用 test 中的配置,如下。

<?php

use herosphp\plugin\orm\Db;
// default
Db::select('SELECT * FROM user;');
Db::connection('default')->select('SELECT * FROM user;');

// test
Db::connection('test')->select('SELECT * FROM user;');

模型中修改 connection 字段,即可使用对应配置,例如一下 Model 使用 test 配置。

<?php

declare(strict_types=1);

namespace app\entity;

use herosphp\plugin\orm\Model;

/**
 * @property int $id
 * @property string $mobile
 * @property string $realname
 */
class User extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'user';

    /**
     * The connection name for the model.
     *
     * @var string
     */
    protected $connection = 'test';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['id', 'mobile', 'realname'];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer'];
}

# 查询构造器

配置好数据库后,便可以使用 herosphp\plugin\orm\Db 进行查询。

# Query 查询类

这里主要包括 Select、属性为 READS SQL DATA 的存储过程、函数等查询语句。

select 方法将始终返回一个数组,数组中的每个结果都是一个 StdClass 对象

<?php

use herosphp\plugin\orm\Db;

$users = Db::select('SELECT * FROM `user` WHERE gender = ?',[1]);  //  返回array 

foreach($users as $user){
    echo $user->name;
}

# Execute 执行类

这里主要包括 InsertUpdateDelete,属性为 MODIFIES SQL DATA 的存储过程等执行语句。

<?php

use herosphp\plugin\orm\Db;

$inserted = Db::insert('INSERT INTO user (id, name) VALUES (?, ?)', [1, 'zhangsan']); // 返回是否成功 bool

$affected = Db::update('UPDATE user set name = ? WHERE id = ?', ['John', 1]); // 返回受影响的行数 int

$affected = Db::delete('DELETE FROM user WHERE id = ?', [1]); // 返回受影响的行数 int

$result = Db::statement("CALL pro_test(?, '?')", [1, 'your words']);  // 返回 bool  CALL pro_test(?,?) 为存储过程,属性为 MODIFIES SQL DATA

# 自动管理数据库事务

你可以使用 Dbtransaction 方法在数据库事务中运行一组操作。如果事务的闭包 Closure 中出现一个异常,事务将会回滚。如果事务闭包 Closure 执行成功,事务将自动提交。一旦你使用了 transaction , 就不再需要担心手动回滚或提交的问题:

<?php
use herosphp\plugin\orm\Db;

Db::transaction(function () {
    Db::table('user')->update(['votes' => 1]);

    Db::table('posts')->delete();
});

# 手动管理数据库事务

如果你想要手动开始一个事务,并且对回滚和提交能够完全控制,那么你可以使用 DbbeginTransaction, commit, rollBack:

use herosphp\plugin\orm\Db;

Db::beginTransaction();
try{
    // Do something...
    Db::commit();
} catch(\Throwable $ex){
    Db::rollBack();
}

# 模型

模型组件衍生于 Eloquent ORM (opens new window),相关操作均可参考 Eloquent ORM 的文档。

上次更新: 10/27/2022, 11:18:25 AM