記錄 dcat-admin 使用 Laravel-activitylog 記錄使用者行為過程中遇到的問題

jarl發表於2023-04-18

更新: 釋出了個擴充套件包,歡迎提意見 jarl/activity-log

在dcat-admin中想要記錄後臺操作記錄,首頁我利用了dcat-admin官方的operation-log擴充套件包,下載下來後發現它是根據http請求記錄的日誌,雖然可以設定哪些請求不記錄,但是還是不夠自定義,記錄的日誌非開發人員還是看不懂的,如下所示

記錄 dcat-admin 使用  Laravel-activitylog 記錄使用者行為過程中遇到的問題
而我想要記錄 “誰操作了什麼” 這種誰都能看懂的日誌記錄,於是乎找上了Laravel-activitylog
簡單的使用就不說了,去看官方文件,我在使用自動記錄模型事件的時候遇上了一些問題。
根據文件我的model最終變成了這樣

namespace App\Models;

use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;

class User extends Model
{
    use HasDateTimeFormatter;
    use SoftDeletes;
    use LogsActivity;

    protected function getDescriptionForEvent(string $eventName): string
    {
        $description = '';
        switch ($eventName) {
            case 'created':
                $description = '管理員' . Auth('admin')->user()->username . '新增了' . $this->table.'表id為' . $this->id . '的資料';
                break;
            case 'updated':
                $description = '管理員' . Auth('admin')->user()->username . '修改了' . $this->table.'表id為' . $this->id . '的資料';
                break;
            case 'deleted':
                $description = '管理員' . Auth('admin')->user()->username . '刪除了' . $this->table.'表id為' . $this->id . '的資料';
                break;
        }
        return $description;
    }

    protected function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logAll() // 記錄所有欄位的更改
            ->dontLogIfAttributesChangedOnly(['updated_at']) // 當只有updated_at 欄位更改時不記錄
            ->logOnlyDirty() // 只有實際發生更改的欄位記錄
            ->dontSubmitEmptyLogs() // 不記錄空日誌
            ->useLogName('users') // 設定日誌名
            ->setDescriptionForEvent(fn (string $eventName) => $this->getDescriptionForEvent($eventName));
    }
}

現在既然這些程式碼在每個類裡都基本一樣了,於是我將它提取成一個trait.

namespace App\Admin\Traits;


use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;

trait LogsActivityTrait
{
    use LogsActivity;

    protected string $logName = '';
    protected function getDescriptionForEvent(string $eventName): string
    {
        $description = '';
        switch ($eventName) {
            case 'created':
                $description = '管理員' . Auth('admin')->user()->username . '新增了' . $this->table.'表id為' . $this->id . '的資料';
                break;
            case 'updated':
                $description = '管理員' . Auth('admin')->user()->username . '修改了' . $this->table.'表id為' . $this->id . '的資料';
                break;
            case 'deleted':
                $description = '管理員' . Auth('admin')->user()->username . '刪除了' . $this->table.'表id為' . $this->id . '的資料';
                break;
        }
        return $description;
    }

    protected function getLogName(): string
    {
        return $this->logName ?: strtolower(class_basename($this)); // 小寫類名作為日誌名方便分類
    }

    protected function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logAll() // 記錄所有欄位的更改
            ->dontLogIfAttributesChangedOnly(['updated_at']) // 當只有updated_at 欄位更改時不記錄
            ->logOnlyDirty() // 只有實際發生更改的欄位記錄
            ->dontSubmitEmptyLogs() // 不記錄空日誌
            ->useLogName($this->getLogName()) // 設定日誌名
            ->setDescriptionForEvent(fn (string $eventName) => $this->getDescriptionForEvent($eventName));
    }
}

這樣每個model裡只需要use LogsActivityTrait;就行,同時logName屬性 和 getDescriptionForEvent方法也可重寫覆蓋,甚至說getActivitylogOptions方法裡的各種方法你想要的不想要的都能自己修改進行自定義
最後再說一點
-Activitylog安裝完後 在activitylog.php配置檔案裡的default_auth_driver屬性預設是null,這樣生成的日誌裡causer_typecauser_id都是null,注意改成你定義的guard,一般後臺是admin,前臺是web,也可以建立箇中介軟體動態設定這個值

public function handle($request, Closure $next, $guard = 'admin')
{
    config()->set('activitylog.default_auth_driver', $guard);

    return $next($request);
}
  • 如果你想自定義設定causer_type和causer_id,可以在LogsActivityTrait裡定義tapActivity方法
    public function tapActivity(Activity $activity, string $eventName)
      {
          $activity->causer_id = 2;
          //$activity->description = '你想要修改的description';
      }
    tapActivity方法裡可以修改任何欄位。
    LogsActivity的sql欄位如下

記錄 dcat-admin 使用  Laravel-activitylog 記錄使用者行為過程中遇到的問題

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章