You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何对比两个同记录对象并获取发生变更的字段

首先纠正你示例代码的逻辑问题:你在修改$before_update并调用save()方法后,该变量本身已经存储了更新后的值,此时再查询得到的$after_update和$before_update内容完全一致,无法做差异对比。

以下是两种可行的实现方案:

方案1:无需二次查询,直接用Laravel Eloquent内置方法获取变更字段

Eloquent模型本身自带修改记录能力,你可以在更新操作前后调用内置方法直接拿到变动内容,不需要额外查两次数据库:

$model = DeliveryRun::find($id);
// 存储更新前的全部原始字段值
$originalValues = $model->getOriginal();

// 执行更新逻辑
$model->name = $request->input('name');
$model->save();

// 直接获取所有发生变更的字段+更新后的值
$changedInfo = $model->getChanges();

返回的$changedInfo是关联数组,键为变动的字段名,值为更新后的字段值。如果需要同时展示新旧值,遍历$changedInfo的键从$originalValues取值对应即可。

方案2:两个独立模型实例的对比方法

如果你确实已经拿到了两个独立的更新前后的模型实例(比如跨请求、跨事务获取的场景),可以用以下自定义方法做对比:

/**
 * 对比两个同表模型实例的字段差异
 * @param $modelBefore 更新前的模型实例
 * @param $modelAfter 更新后的模型实例
 * @return array 差异字段数组,包含每个字段的新旧值
 */
function compareModelDiff($modelBefore, $modelAfter): array
{
    // 仅提取模型的业务字段值,排除模型内置属性
    $beforeAttrs = $modelBefore->getAttributes();
    $afterAttrs = $modelAfter->getAttributes();

    $diffResult = [];
    foreach ($beforeAttrs as $field => $oldVal) {
        $newVal = $afterAttrs[$field] ?? null;
        // 用严格比较避免数字、字符串隐式转换导致的误判
        if ($oldVal !== $newVal) {
            $diffResult[$field] = [
                'old_value' => $oldVal,
                'new_value' => $newVal
            ];
        }
    }
    return $diffResult;
}

// 调用示例
$changedFields = compareModelDiff($before_update, $after_update);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 18:15:08