You need to enable JavaScript to run this app. 如何使用Eloquent编写支持MariaDB系统版本控制的查询
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Eloquent编写支持MariaDB系统版本控制的查询

基于Eloquent实现MariaDB系统版本化历史查询的落地方案
  • 若使用 Laravel 9.18 及以上版本,框架已原生内置对MariaDB系统版本控制(时态表)的查询语法支持,无需拼接整段原生SQL。
    对应等价查询可直接调用查询构造器内置的forAllTime()方法,Eloquent模型、DB门面场景均可直接使用:
    // 基于Address模型(对应addresses表)的查询写法
    $addressHistory = Address::query()
        ->forAllTime()
        ->where('id', $id)
        ->get();
    
    // 基于DB查询构造器的等价写法
    $addressHistory = DB::table('addresses')
        ->forAllTime()
        ->where('id', $id)
        ->get();
    
    该方法生成的SQL与你原本编写的SELECT * FROM addresses FOR SYSTEM_TIME ALL WHERE id = ?完全等价,框架会自动完成数据库语法适配,同时自动对查询参数做绑定处理,避免此前直接将$id拼接进SQL字符串带来的SQL注入风险。
    除查询全量历史版本外,框架还内置了其他常用的时态查询方法,覆盖不同历史数据查询场景:
    • 查询指定时间点的表版本:调用forPointInTime($timestamp)方法,自动生成FOR SYSTEM_TIME AS OF 对应时间戳的语法
    • 查询指定时间区间内的所有版本记录:调用forTimeBetween($startTime, $endTime)方法,自动生成FOR SYSTEM_TIME BETWEEN 开始时间 AND 结束时间的语法
  • 若使用的Laravel版本低于9.18,无上述内置方法,也无需全程手写原生SQL,可通过查询构造器宏自定义封装对应方法,复用查询逻辑:
    首先在App\Providers\AppServiceProvider的boot方法中注册宏:
    use Illuminate\Database\Query\Builder;
    
    Builder::macro('forAllSystemTime', function () {
        // 为主表添加系统时间全量查询语法
        $this->from = $this->from . ' FOR SYSTEM_TIME ALL';
        // 为关联的join表同步添加对应语法
        $this->joins = collect($this->joins)->map(function ($joinClause) {
            $joinClause->table = $joinClause->table . ' FOR SYSTEM_TIME ALL';
            return $joinClause;
        })->all();
    
        return $this;
    });
    
    注册完成后,可在任意查询中直接调用该自定义方法,使用体验与内置方法完全一致,同样会自动完成参数绑定,无需手动拼接SQL字符串。
  • 绑定了系统版本控制的表,Eloquent模型默认执行的查询会自动过滤为当前生效的最新版本,与普通表的查询体验无差异,仅当主动调用上述历史查询方法时,才会拉取全量历史版本数据,无需额外在模型中编写特殊适配代码。

内容的提问来源于stack exchange,提问作者ayano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 17:54:01