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

Laravel如何实现行内单元格变更记录?突破updated_at局限

嘿,这个问题我之前做Laravel项目的时候刚好碰到过!确实,Laravel自带的updated_at字段只能帮我们追踪更新时间,但要搞清楚具体哪些字段被修改了,其实有几个实用的方案,我给你梳理一下:

方案一:用Eloquent原生方法手动对比

Laravel的模型自带getOriginal()方法,可以获取到模型更新前的原始属性值,我们可以在模型的updated事件里对比原始值和更新后的值,找出差异:

protected static function booted()
{
    static::updated(function ($model) {
        // 获取更新前的原始数据
        $originalValues = $model->getOriginal();
        // 获取更新后的当前数据
        $currentValues = $model->getAttributes();
        
        // 筛选出真正有变化的字段(排除自动维护的时间字段)
        $changedFields = [];
        foreach ($currentValues as $field => $value) {
            if (!in_array($field, ['created_at', 'updated_at']) && $originalValues[$field] !== $value) {
                $changedFields[$field] = [
                    'old_value' => $originalValues[$field],
                    'new_value' => $value
                ];
            }
        }
        
        // 如果有变化,就把差异存入日志表
        if (!empty($changedFields)) {
            // 这里假设你已经创建了ActivityLog模型和对应的表
            \App\Models\ActivityLog::create([
                'model_type' => get_class($model),
                'model_id' => $model->id,
                'changes' => json_encode($changedFields),
                'operated_at' => now(),
                'operator_id' => auth()->id() // 还能记录操作人ID
            ]);
        }
    });
}

这个方案完全依赖Laravel原生功能,不需要额外安装包,适合轻量需求的场景。

方案二:用成熟的第三方包快速实现

如果不想自己写重复逻辑,社区有非常好用的现成包,比如spatie/laravel-activitylog,它能自动帮你追踪模型的增删改操作,还能精准记录字段的新旧变化:

  1. 先安装包:
composer require spatie/laravel-activitylog
  1. 发布迁移文件和配置文件:
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider"
  1. 运行迁移创建日志表:
php artisan migrate
  1. 在需要追踪的模型里引入trait并配置:
use Spatie\Activitylog\Traits\LogsActivity;

class Post extends Model
{
    use LogsActivity;
    
    // 配置要追踪的字段(如果用$logFillable则追踪所有fillable字段)
    protected $logAttributes = ['title', 'content', 'status'];
    
    // 自定义日志的描述文本
    public function getDescriptionForEvent(string $eventName): string
    {
        return "文章已被{$eventName}";
    }
}

之后每次模型更新,这个包就会自动把字段的变化记录到activity_log表中,你可以直接通过模型关联或者包提供的方法查询历史记录,非常省心。

方案三:自定义观察者实现复杂逻辑

如果你的项目有特殊的日志规则(比如不同模型需要不同的追踪逻辑),可以用Laravel的观察者模式来实现:

  1. 生成对应模型的观察者:
php artisan make:observer PostObserver --model=Post
  1. 在观察者的updated方法里实现差异对比和日志记录:
namespace App\Observers;

use App\Models\Post;
use App\Models\ActivityLog;

class PostObserver
{
    public function updated(Post $post)
    {
        $original = $post->getOriginal();
        $current = $post->getAttributes();
        
        // 只追踪我们关心的字段,并且过滤掉没有变化的内容
        $changes = array_filter($current, function ($value, $key) use ($original) {
            return in_array($key, ['title', 'content']) && $original[$key] !== $value;
        }, ARRAY_FILTER_USE_BOTH);
        
        if (!empty($changes)) {
            ActivityLog::create([
                'model' => 'Post',
                'model_id' => $post->id,
                'changes' => json_encode($changes),
                'operator_id' => auth()->id()
            ]);
        }
    }
}
  1. 在AppServiceProvider的boot方法里注册观察者:
public function boot()
{
    Post::observe(PostObserver::class);
}

这种方式灵活性最高,适合需要定制化日志规则的场景。

需要注意的是,对于JSON字段或者关联模型的变化,上面的基础逻辑可能需要额外处理,但已经能覆盖大部分常规的字段追踪需求啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:25:36