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

如何自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:52:39