如何自定义Laravel Activity Log添加元数据?Spatie包配置问题
在Laravel中扩展Spatie Activitylog添加自定义元数据(IP、用户代理等)
一、先排查你遇到的tapActivity不生效问题
大概率是你操作方式不对,常见坑点:
- 没正确继承Spatie的原服务提供者,而是新建了普通Provider
- 直接给
$activity赋值属性(比如$activity->ip = xxx),但Spatie的额外元数据存在properties这个JSON字段里,不是直接加模型属性 - 自定义了Activity模型但没配置到
config/activitylog.php里
二、正确的tapActivity实现代码
直接修改或新建继承自Spatie的服务提供者:
<?php namespace App\Providers; use Illuminate\Support\Facades\Request; use Spatie\Activitylog\ActivitylogServiceProvider as SpatieServiceProvider; use Spatie\Activitylog\Models\Activity; class ActivitylogServiceProvider extends SpatieServiceProvider { public function boot() { parent::boot(); $this->tapActivity(function (Activity $activity) { // 区分HTTP请求和CLI命令场景 $metadata = []; if (!app()->runningInConsole()) { $metadata['ip_address'] = Request::ip(); $metadata['user_agent'] = Request::userAgent(); $metadata['request_path'] = Request::path(); } else { $metadata['cli_command'] = implode(' ', $_SERVER['argv'] ?? []); } // 合并到原有properties中,保留默认日志的其他数据 $activity->properties = $activity->properties->merge($metadata); }); } }
然后确保在config/app.php的providers数组里替换掉原Spatie的Provider:
'providers' => [ // ... // Spatie\Activitylog\ActivitylogServiceProvider::class, App\Providers\ActivitylogServiceProvider::class, ],
三、其他可选实现方式(最佳实践)
1. 用事件监听扩展
如果不想修改Provider,可以监听Activity创建事件:
在app/Providers/EventServiceProvider.php中注册监听:
protected $listen = [ \Spatie\Activitylog\Events\ActivityLogged::class => [ \App\Listeners\AddMetadataToActivity::class, ], ];
创建对应的Listener文件app/Listeners/AddMetadataToActivity.php:
<?php namespace App\Listeners; use Illuminate\Support\Facades\Request; use Spatie\Activitylog\Events\ActivityLogged; class AddMetadataToActivity { public function handle(ActivityLogged $event) { if (!app()->runningInConsole()) { $event->activity->properties = $event->activity->properties->merge([ 'ip_address' => Request::ip(), 'user_agent' => Request::userAgent(), ]); // 事件触发时日志已创建,必须手动保存修改 $event->activity->save(); } } }
2. 自定义Activity模型(适合复杂场景)
如果需要频繁读取这些元数据,或者要加自定义访问器,可以创建自己的Activity模型:
<?php namespace App\Models; use Spatie\Activitylog\Models\Activity as SpatieActivity; class Activity extends SpatieActivity { // 给IP字段加访问器,直接通过$activity->ip_address获取 public function getIpAddressAttribute() { return $this->properties->get('ip_address'); } // 同理给用户代理加访问器 public function getUserAgentAttribute() { return $this->properties->get('user_agent'); } }
然后在config/activitylog.php中配置使用自定义模型:
'model' => App\Models\Activity::class,
四、验证生效情况
执行任意会生成操作日志的行为后,查看activities表的properties字段,或者用代码调试:
$latestActivity = \App\Models\Activity::latest()->first(); dd($latestActivity->properties);
你会看到包含ip_address、user_agent等自定义字段的JSON数据。
内容的提问来源于stack exchange,提问作者Pavel Rahman
相关产品推荐
相关产品推荐

