Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Laravel Activitylog
https://github.com/spatie/laravel-activitylog
Admin
A package for Laravel that provides easy-to-use functions to log user activities and automatically
...
Tokens:
15,673
Snippets:
119
Trust Score:
-
Update:
5 months ago
Context
Skills
Chat
Benchmark
91.7
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Laravel Activity Log Laravel Activity Log is a Laravel package by Spatie that provides easy-to-use functionality for logging user activities and tracking model changes within Laravel applications. The package stores all activity in a database table and provides both manual logging capabilities and automatic model event logging through Eloquent observers. The package offers a fluent API for recording activities with context about who performed the action (causer), what was affected (subject), custom properties, and automatic change tracking. It supports logging model events (created, updated, deleted, restored), querying activities with scopes, batch operations, and customizable logging options per model. All activities are stored in a polymorphic structure allowing any Eloquent model to be logged. ## Manual Activity Logging Log custom activities with description and retrieve them from the database. ```php use Spatie\Activitylog\Models\Activity; // Simple activity log activity()->log('User viewed dashboard'); // Retrieve all activities $activities = Activity::all(); $lastActivity = Activity::all()->last(); echo $lastActivity->description; // 'User viewed dashboard' ``` ## Activity Logging with Context Log activities with subject, causer, and custom properties for rich audit trails. ```php use App\Models\Article; use App\Models\User; use Spatie\Activitylog\Models\Activity; $article = Article::find(1); $user = User::find(1); // Log with full context activity() ->performedOn($article) ->causedBy($user) ->withProperties(['custom_field' => 'custom_value', 'ip' => '192.168.1.1']) ->log('Article was reviewed'); // Retrieve and access activity data $activity = Activity::all()->last(); echo $activity->description; // 'Article was reviewed' echo $activity->subject->title; // Article title echo $activity->causer->name; // User name echo $activity->getExtraProperty('custom_field'); // 'custom_value' ``` ## Automatic Model Event Logging Automatically log model changes using the LogsActivity trait on your Eloquent models. ```php use Illuminate\Database\Eloquent\Model; use Spatie\Activitylog\Traits\LogsActivity; use Spatie\Activitylog\LogOptions; class Article extends Model { use LogsActivity; protected $fillable = ['title', 'content', 'status']; public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() ->logOnly(['title', 'content', 'status']) ->logOnlyDirty() ->dontSubmitEmptyLogs(); } } // Model changes are automatically logged $article = Article::create([ 'title' => 'New Article', 'content' => 'Article content', 'status' => 'draft' ]); $article->update(['title' => 'Updated Title']); // Retrieve the activity $activity = Activity::forSubject($article)->get()->last(); echo $activity->description; // 'updated' echo $activity->event; // 'updated' // Access changes $changes = $activity->changes(); // [ // 'attributes' => ['title' => 'Updated Title', 'content' => 'Article content', 'status' => 'draft'], // 'old' => ['title' => 'New Article', 'content' => 'Article content', 'status' => 'draft'] // ] ``` ## Advanced LogOptions Configuration Configure granular logging behavior for each model with fluent LogOptions API. ```php use Illuminate\Database\Eloquent\Model; use Spatie\Activitylog\Traits\LogsActivity; use Spatie\Activitylog\LogOptions; class Product extends Model { use LogsActivity; protected $fillable = ['name', 'price', 'stock', 'updated_at']; public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() ->logAll() // Log all attributes ->logExcept(['updated_at']) // Except these ->logOnlyDirty() // Only when actually changed ->dontLogIfAttributesChangedOnly(['updated_at']) // Don't log if only these changed ->useLogName('products') ->setDescriptionForEvent(fn(string $eventName) => "Product was {$eventName}"); } } $product = Product::create(['name' => 'Laptop', 'price' => 999.99, 'stock' => 10]); $product->update(['price' => 899.99]); $activity = Activity::inLog('products')->forSubject($product)->first(); echo $activity->description; // 'Product was updated' echo $activity->log_name; // 'products' ``` ## Querying Activities with Scopes Filter and retrieve activities using built-in Eloquent query scopes. ```php use Spatie\Activitylog\Models\Activity; use App\Models\User; use App\Models\Article; $user = User::find(1); $article = Article::find(5); // Query by log name $adminActivities = Activity::inLog('admin')->get(); $multipleLogActivities = Activity::inLog(['admin', 'user'])->get(); // Query by causer $userActivities = Activity::causedBy($user)->get(); // Query by subject $articleActivities = Activity::forSubject($article)->get(); // Query by event $createdActivities = Activity::forEvent('created')->get(); $updatedActivities = Activity::forEvent('updated')->get(); // Query by batch $batchActivities = Activity::forBatch('550e8400-e29b-41d4-a716-446655440000')->get(); $allBatchedActivities = Activity::hasBatch()->get(); // Combine scopes $specificActivities = Activity::inLog('admin') ->causedBy($user) ->forEvent('updated') ->whereBetween('created_at', ['2024-01-01', '2024-12-31']) ->get(); ``` ## Batch Operations Group multiple activities together with a shared batch UUID for related operations. ```php use Spatie\Activitylog\Facades\LogBatch; use Spatie\Activitylog\Models\Activity; use App\Models\Product; // Using withinBatch closure LogBatch::withinBatch(function ($batchUuid) { $product1 = Product::create(['name' => 'Product 1', 'price' => 10]); $product2 = Product::create(['name' => 'Product 2', 'price' => 20]); $product3 = Product::create(['name' => 'Product 3', 'price' => 30]); return $batchUuid; // All creates share this batch UUID }); // Manual batch control LogBatch::startBatch(); $product1 = Product::create(['name' => 'Product A', 'price' => 100]); $product2 = Product::create(['name' => 'Product B', 'price' => 200]); $batchUuid = LogBatch::getUuid(); LogBatch::endBatch(); // Query all activities in this batch $batchActivities = Activity::forBatch($batchUuid)->get(); foreach ($batchActivities as $activity) { echo "{$activity->description} - {$activity->subject->name}\n"; } ``` ## Using Log Names and Custom Properties Organize activities into different logs and attach custom metadata. ```php use Spatie\Activitylog\Models\Activity; // Use specific log name activity('authentication')->log('User logged in'); activity('payments')->log('Payment processed'); // Use fluent API for log names activity() ->useLog('admin') ->withProperties(['role' => 'super_admin', 'ip' => '10.0.0.1']) ->log('Admin performed sensitive action'); // Alternative syntax activity() ->inLog('audit') ->withProperty('action_type', 'delete') ->withProperty('reason', 'GDPR request') ->log('Data deletion completed'); // Retrieve by log name $authLogs = Activity::inLog('authentication')->get(); $paymentLogs = Activity::inLog('payments')->get(); $auditLogs = Activity::inLog('audit')->get(); $adminActivity = Activity::inLog('admin')->first(); echo $adminActivity->getExtraProperty('role'); // 'super_admin' ``` ## Anonymous Activities and Custom Causers Log activities without a causer or with custom causer assignments. ```php use App\Models\User; // Log anonymous activity (no causer) activity() ->causedByAnonymous() ->log('Public API accessed'); // Alternative syntax activity() ->byAnonymous() ->log('Guest viewed homepage'); // Custom causer assignment $admin = User::find(1); activity() ->causedBy($admin) ->log('Admin reviewed logs'); // Using by() alias activity() ->by($admin) ->log('Admin performed action'); // Causer by ID activity() ->causedBy(5) ->log('User ID 5 performed action'); ``` ## Custom Timestamps and Event Names Set custom creation timestamps and event names for activities. ```php use Carbon\Carbon; // Custom timestamp activity() ->createdAt(Carbon::now()->subHours(2)) ->log('Backfilled historical activity'); // Custom event name activity() ->event('password_reset') ->log('User requested password reset'); // Combine with other methods activity() ->event('export') ->createdAt(Carbon::parse('2024-01-15 10:30:00')) ->withProperties(['format' => 'csv', 'rows' => 1500]) ->log('Data export completed'); ``` ## Temporarily Disabling Logging Disable activity logging for specific operations to prevent noise. ```php use Spatie\Activitylog\Facades\Activity; use App\Models\Product; // Disable logging globally Activity::disableLogging(); $product = Product::create(['name' => 'Test', 'price' => 1]); // Not logged Activity::enableLogging(); // Use closure to automatically re-enable Activity::withoutLogs(function() { $product1 = Product::create(['name' => 'Bulk 1', 'price' => 10]); $product2 = Product::create(['name' => 'Bulk 2', 'price' => 20]); $product3 = Product::create(['name' => 'Bulk 3', 'price' => 30]); // None of these are logged }); // Logging automatically re-enabled // Disable logging per model instance $product = Product::find(1); $product->disableLogging(); $product->update(['price' => 999]); // Not logged $product->enableLogging(); $product->update(['stock' => 5]); // This is logged ``` ## Cleaning Old Activity Logs Remove old activity logs using the built-in Artisan command for maintenance. ```bash # Clean activities older than configured days (default: 365) php artisan activitylog:clean # Clean specific log name php artisan activitylog:clean admin # Clean with custom age in days php artisan activitylog:clean --days=90 # Force in production without confirmation php artisan activitylog:clean --force # Clean specific log with custom age php artisan activitylog:clean payments --days=30 ``` ## Retrieving Activity Relationships Access subject and causer models through polymorphic relationships. ```php use Spatie\Activitylog\Models\Activity; use App\Models\Article; use App\Models\User; $activity = Activity::first(); // Access the subject (what was affected) $subject = $activity->subject; // Returns Article, Product, etc. echo $subject->title; // Access subject attributes // Access the causer (who performed the action) $causer = $activity->causer; // Returns User model echo $causer->email; // Access causer attributes // Query activities with eager loading $activities = Activity::with(['subject', 'causer'])->get(); foreach ($activities as $activity) { if ($activity->subject) { echo "{$activity->causer->name} {$activity->description} {$activity->subject->title}\n"; } } // Filter by polymorphic type $articleActivities = Activity::where('subject_type', Article::class)->get(); ``` ## Configuration Options Configure package behavior through the published configuration file. ```php // config/activitylog.php return [ // Enable/disable logging globally 'enabled' => env('ACTIVITY_LOGGER_ENABLED', true), // Days to keep logs before cleaning 'delete_records_older_than_days' => 365, // Default log name when none specified 'default_log_name' => 'default', // Custom auth driver for resolving causers 'default_auth_driver' => null, // Return soft deleted models in subject relation 'subject_returns_soft_deleted_models' => false, // Custom activity model class 'activity_model' => \Spatie\Activitylog\Models\Activity::class, // Database table name 'table_name' => env('ACTIVITY_LOGGER_TABLE_NAME', 'activity_log'), // Database connection 'database_connection' => env('ACTIVITY_LOGGER_DB_CONNECTION'), ]; ``` ## Installation and Database Setup Install the package and set up the required database tables. ```bash # Install via Composer composer require spatie/laravel-activitylog # Publish migrations php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations" # Run migrations php artisan migrate # Publish configuration (optional) php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-config" ``` ## Summary Laravel Activity Log provides a comprehensive solution for tracking user activities and model changes in Laravel applications. The package is ideal for audit trails, compliance requirements, debugging, user behavior analytics, and administrative monitoring. It supports both manual logging through the fluent `activity()` helper and automatic model event tracking via the `LogsActivity` trait. The package integrates seamlessly with Laravel's Eloquent ORM using polymorphic relationships to track any model as subject or causer. Common integration patterns include adding the `LogsActivity` trait to models that need automatic change tracking, using the `activity()` helper for custom business logic logging, implementing batch operations for grouped activities, and creating custom log names to organize different types of activities. The built-in query scopes, configuration options, and cleanup commands make it suitable for applications of any size, from small projects to large enterprise systems requiring detailed audit trails.