spatie/laravel-activitylog
Log user and model activity in Laravel with a simple API. Automatically record Eloquent model events, link actions to subjects and causers, store custom properties, and query a dedicated activity_log table for auditing and history.
Installation:
composer require spatie/laravel-activitylog
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations"
php artisan migrate
(Optional: Publish config with --tag="activitylog-config")
First Log Entry:
use Spatie\Activitylog\Facades\Activity;
Activity::log('User accessed dashboard');
Query Logs:
$logs = \Spatie\Activitylog\Models\Activity::latest()->take(10)->get();
Log a user action (e.g., model update) with automatic causer resolution:
$user = auth()->user();
$post = Post::find(1);
$post->title = 'Updated Title';
$post->save(); // Auto-logged with causer=$user
Manual Logging:
Activity::log('Custom event')
->performedOn($model)
->causedBy($user)
->withProperties(['ip' => request()->ip()]);
Model Event Logging:
Add use LogsActivity; to your model and configure getActivitylogOptions():
public function getActivitylogOptions(): LogOptions {
return LogOptions::defaults()
->logOnly(['title', 'status'])
->dontLogIfAttributesChangedOnly(['status']);
}
Batch Processing:
Use beforeLogging hook to group activities:
Activity::beforeLogging(function ($activity) {
$activity->properties->put('batch_id', request()->batch_id);
});
Middleware: Set default causer in middleware:
public function handle($request, Closure $next) {
Activity::defaultCauser($request->user());
return $next($request);
}
API Responses: Attach logs to API responses:
return response()->json([
'data' => $post,
'logs' => $post->activity()->latest()->take(5)->get(),
]);
Admin Panels: Use activity() facade in admin panels (e.g., Nova, Filament) to show audit trails.
Performance:
properties.logOnlyDirty() to reduce database writes for unchanged attributes.Causer Resolution:
causer_id is null, ensure defaultCauser() is set or a CauserResolver callback is registered.UUID Models:
Morphs with UUID fields if your models use UUIDs.Event Overrides:
Observers, ensure LogsActivity isn’t called twice (e.g., via both trait and observer).Missing Logs:
Check if getActivitylogOptions() is properly defined and events (e.g., updated) are being triggered.
Empty Changes:
Use logEmptyChanges() if you need to log events even when no attributes change.
Custom Activity Model:
Extend \Spatie\Activitylog\Models\Activity to add fields (e.g., batch_uuid):
php artisan make:model ActivityLogExtension -m
Log Filters: Create scopes for common queries:
public function scopeForModel($query, $model) {
return $query->where('subject_type', $model::class);
}
Webhooks:
Trigger external actions (e.g., Slack alerts) via beforeLogging:
Activity::beforeLogging(function ($activity) {
if ($activity->description === 'Password changed') {
Slack::alert($activity->causer, $activity->description);
}
});
admin, api) to segment activities.softDeletes() to the Activity model if you need to purge logs.Activity::shouldReceive('log')->once() in PHPUnit to verify logging.How can I help you explore Laravel packages today?