mtphp 文档

模型(Model / ORM-lite)

Mtphp\Database\Model —— 轻量模型,用最简单的静态方法完成最常见的增删改查,无需写 SQL、无需复杂配置。

namespace App\Models;

use Mtphp\Database\Model;

class User extends Model
{
    protected static ?string $table = 'user';      // 表名(不含前缀);可省略,默认按类名推导为 user
    protected static string $primaryKey = 'id';    // 主键列名(默认 id)
}

User::find(1);                                   // 按主键查一条(不存在返回 null)
User::where('age', '>', 18)->get();              // 链式查询(返回数组)
User::where('age', '>', 18)->orderBy('id','desc')->limit(10)->get();
User::findBy('name', '张三');                     // 按某列查一条
User::create(['name' => '张三']);                 // 插入,返回自增主键 ID
User::update(1, ['name' => '李四']);              // 按主键更新,返回影响行数
User::delete(1);                                 // 按主键删除,返回影响行数
User::count();                                   // 计数

要点:

13.1 类型转换(casts)与访问器 / 修改器

声明 $casts 后,字段在读出(DB→应用)与写入(应用→DB)时自动按类型处理,无需手动 json_encode / (int) 等。

class User extends Model
{
    // 支持:int/integer、float、bool/boolean、string、json/array、datetime/date/timestamp
    protected static array $casts = [
        'is_admin'   => 'bool',
        'score'      => 'int',
        'meta'      => 'json',     // 入库 JSON 字符串,读出为数组
        'created_at' => 'datetime', // 字符串原样保留(或整型时间戳转 Y-m-d H:i:s)
    ];
}

$u = User::find(1);
$u['is_admin'];   // 已是 bool
$u['meta'];       // 已是数组(无需手动 json_decode)

13.2 关联计数(withCount)

一对多 / 一对一场景下,常需要“每个用户发了多少条帖子”这类计数。用 withCount 一条查询搞定,结果行会多出 {关联名}_count 字段:

$users = User::withCount('posts')->get();
foreach ($users as $u) {
    echo $u['name'] . ' 发了 ' . $u['posts_count'] . ' 篇';
}

// 可与 with() 预加载并用:行内 posts 数组长度 === posts_count
$users = User::with('posts')->withCount('posts')->get();

底层按 SELECT 外键, COUNT(*) ... WHERE 外键 IN (...) GROUP BY 外键 批量统计,避免 N+1;withCount 同样支持 'a.b' 嵌套写法(按关联定义递归)。

13.3 模型事件(Model Events)

在「写操作前 / 后」挂载钩子(如自动填充、审计、拦截非法写入),无需改动 create/update/delete 内部逻辑。支持的事件:

阶段事件
写前(可拦截)saving、creating、updating、deleting、restoring、forceDeleting
写后saved、created、updated、deleted、restored、forceDeleted

use Mtphp\Database\Model;

class User extends Model
{
    protected static ?string $table = 'users';
}

// 方式一:直接注册回调(写前事件返回 false 可拦截本次写操作)
User::registerModelEvent('creating', function (string $class, $payload) {
    if (empty($payload['name'])) {
        return false;            // 拦截插入,create() 返回 0
    }
});
User::registerModelEvent('created', function (string $class, $payload) {
    // $payload 含写入数据与自增主键:$payload['id']
});

// 方式二:观察者(方法名即事件名,自动绑定)
class UserObserver
{
    public function creating(string $class, $payload) { /* ... */ }
    public function created(string $class, $payload)  { /* ... */ }
}
User::observe(UserObserver::class);   // 或传入实例:User::observe(new UserObserver());

$id = User::create(['name' => 'neo']);   // 触发 saving→creating→(写入)→created→saved
User::update($id, ['name' => 'neo2']);   // 触发 saving→updating→(写入)→updated→saved
User::delete($id);                      // 触发 deleting→(写入)→deleted

要点: