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

如何在Laravel模型中使用Spatie Laravel-activitylog记录关联信息?

在Laravel模型中使用Spatie Laravel-activitylog记录完整日志的解决方案

我来帮你搞定这个问题!其实在模型层面实现Spatie活动日志记录,同时确保subject和causer的ID、类型正确存储,有两种非常实用的方式,完全符合Laravel的开发习惯:

方法一:使用模型观察者(推荐)

模型观察者是处理模型事件最清晰的方式,适合需要记录多个事件(创建、编辑、删除等)的场景:

  1. 生成观察者类
    运行Artisan命令创建对应模型的观察者:
php artisan make:observer ContentObserver --model=Content

(把Content换成你的实际模型名)

  1. 在观察者中编写日志逻辑
    打开生成的app/Observers/ContentObserver.php,添加事件处理方法,这里以updated事件为例:
namespace App\Observers;

use App\Models\Content;
use Spatie\Activitylog\Facades\Activity;

class ContentObserver
{
    public function updated(Content $content)
    {
        // 先获取当前登录用户,避免无用户场景报错
        $currentUser = auth()->user();
        
        if ($currentUser) {
            Activity::causedBy($currentUser)
                ->performedOn($content)
                ->log('edited');
            
            // 可选:添加自定义属性到日志中
            // ->withProperties([
            //     'old_title' => $content->getOriginal('title'),
            //     'new_title' => $content->title
            // ]);
        }
    }

    // 可以按需添加created、deleted、restored等事件的处理逻辑
    public function created(Content $content)
    {
        $currentUser = auth()->user();
        if ($currentUser) {
            Activity::causedBy($currentUser)
                ->performedOn($content)
                ->log('created');
        }
    }
}
  1. 注册观察者
    在app/Providers/AppServiceProvider.php的boot方法中注册观察者:
use App\Models\Content;
use App\Observers\ContentObserver;

public function boot()
{
    Content::observe(ContentObserver::class);
}

方法二:直接在模型的boot方法中绑定事件

如果你的需求比较简单,不想单独创建观察者文件,可以直接在模型内部处理:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Facades\Activity;

class Content extends Model
{
    protected static function boot()
    {
        parent::boot();

        // 监听更新事件
        static::updated(function ($content) {
            $currentUser = auth()->user();
            if ($currentUser) {
                Activity::causedBy($currentUser)
                    ->performedOn($content)
                    ->log('edited');
            }
        });

        // 可添加其他事件
        static::created(function ($content) {
            $currentUser = auth()->user();
            if ($currentUser) {
                Activity::causedBy($currentUser)
                    ->performedOn($content)
                    ->log('created');
            }
        });
    }
}

关键注意事项

  • 确保获取到当前用户:模型中默认没有用户上下文,所以必须用auth()->user()获取当前登录用户,同时要判断用户是否存在(比如命令行执行、队列任务中没有HTTP会话,用户会为null),避免报错。
  • 必须明确指定causedBy和performedOn:这两个方法是填充causer_id、causer_type以及subject_id、subject_type的关键,缺一不可。
  • 非HTTP场景的处理:如果需要在命令行或队列中记录日志,可以提前设置一个“系统用户”作为默认causer,比如:
// 当auth()->user()为null时使用系统用户
$causer = auth()->user() ?? User::find(1); // 假设ID为1的是系统用户
Activity::causedBy($causer)->performedOn($content)->log('edited');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:13:14