Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Activitylog Laravel Package

spatie/laravel-activitylog

Log user and model activity in Laravel with a simple API. Automatically record Eloquent events, track subjects and causers, attach custom properties, and query everything via the Activity model. Stores logs in the activity_log table.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. 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")

  2. First Log Entry:

    use Spatie\Activitylog\Facades\Activity;
    
    Activity::log('User accessed dashboard');
    
  3. Query Logs:

    $logs = \Spatie\Activitylog\Models\Activity::latest()->take(10)->get();
    

First Use Case: Audit Trail for Admin Panel

// Log user actions on a model
$post = Post::find(1);
activity()->performedOn($post)->causedBy(auth()->user())->log('Published post');

// Retrieve recent activity for a user
$recentActivity = \Spatie\Activitylog\Models\Activity::where('causer_id', auth()->id())
    ->latest()->take(5)->get();

Implementation Patterns

Core Workflows

1. Manual Logging

// Basic logging
activity()->log('System backup initiated');

// With metadata
activity()
    ->performedOn($invoice)
    ->causedBy($user)
    ->withProperties(['status' => 'paid'])
    ->log('Invoice marked as paid');

// Using custom log name
activity('audit')->log('Admin deleted user');

2. Automatic Model Event Logging

// In Post model
use Spatie\Activitylog\Traits\LogsActivity;

class Post extends Model
{
    use LogsActivity;

    protected static $logAttributes = ['title', 'content'];
    protected static $logOnlyDirty = true;
}

Triggered automatically on:

  • created (description: "created")
  • updated (description: "updated")
  • deleted (description: "deleted")

3. Querying Logs

// Find all activities for a model
$postActivities = \Spatie\Activitylog\Models\Activity::where('subject_type', Post::class)
    ->where('subject_id', $post->id)->get();

// Filter by description
$paymentActivities = \Spatie\Activitylog\Models\Activity::where('description', 'like', '%paid%')->get();

// Get attribute changes
$activity = \Spatie\Activitylog\Models\Activity::find(1);
$changes = $activity->attribute_changes;

4. Admin Panel Integration

// Controller method
public function auditLog()
{
    $logs = \Spatie\Activitylog\Models\Activity::with(['causer', 'subject'])
        ->latest()->paginate(20);

    return view('admin.audit', compact('logs'));
}

Advanced Patterns

Custom Log Descriptions

// Override default descriptions
use Spatie\Activitylog\LogOptions;

class Post extends Model
{
    use LogsActivity;

    protected static function getActivityDescriptionForEvent($eventName)
    {
        return match($eventName) {
            'created' => 'New post published',
            'updated' => 'Post content updated',
            default => parent::getActivityDescriptionForEvent($eventName),
        };
    }
}

Conditional Logging

// Only log if sensitive data changes
$post->update([
    'title' => 'New Title',
    'content' => 'Updated Content',
    'is_published' => true,
]);

if ($post->wasChanged('is_published')) {
    activity()->performedOn($post)->log('Post publication status changed');
}

Bulk Activity Retrieval

// Get all activities for current user
$myActivities = auth()->user()->activities()->latest()->get();

// Get activities with eager loading
$activities = \Spatie\Activitylog\Models\Activity::with(['causer', 'subject'])
    ->whereHas('subject', fn($q) => $q->where('type', Post::class))
    ->get();

Custom Activity Model

// app/Models/CustomActivity.php
use Spatie\Activitylog\Models\Activity as BaseActivity;

class CustomActivity extends BaseActivity
{
    protected $table = 'custom_activity_logs';
    protected $connection = 'mysql_custom';
}

// Update config
'activity_model' => \App\Models\CustomActivity::class,

Gotchas and Tips

Common Pitfalls

  1. Performance with Large Logs

    • Issue: Querying millions of logs can be slow.
    • Fix: Add indexes to activity_log table:
      Schema::table('activity_log', function (Blueprint $table) {
          $table->index(['subject_type', 'subject_id']);
          $table->index(['causer_id']);
          $table->index(['log_name']);
          $table->index(['created_at']);
      });
      
    • Tip: Use clean command regularly:
      php artisan activitylog:clean
      
  2. Circular References in Properties

    • Issue: Logging Eloquent models as properties can cause serialization errors.
    • Fix: Convert to arrays:
      activity()->withProperties([
          'user_data' => auth()->user()->toArray()
      ])->log('Action performed');
      
  3. Soft Deletes

    • Issue: Subject models might be soft-deleted but still referenced.
    • Fix: Enable in config:
      'include_soft_deleted_subjects' => true,
      
  4. UUID Models

    • Issue: Default migration assumes integer IDs.
    • Fix: Modify migration or use:
      Schema::create('activity_log', function (Blueprint $table) {
          $table->id();
          $table->string('subject_type');
          $table->uuid('subject_id')->nullable();
          // ...
      });
      
  5. Memory Leaks

    • Issue: Eager loading all activities with relationships can consume memory.
    • Fix: Use cursor or chunking:
      \Spatie\Activitylog\Models\Activity::cursor()->get();
      

Debugging Tips

  1. Check Logged Properties

    $activity = \Spatie\Activitylog\Models\Activity::find(1);
    dd($activity->properties); // View raw properties
    
  2. Verify Event Logging

    // Temporarily enable all logging
    \Spatie\Activitylog\Activity::enableLogging();
    
    // Check if events are firing
    event(new \Illuminate\Database\Eloquent\Model\Creating($model));
    
  3. Inspect Activity Model

    // Dump activity structure
    \Spatie\Activitylog\Models\Activity::first()->toArray();
    

Configuration Quirks

  1. Default Auth Driver

    • If using multiple auth systems, specify:
      'default_auth_driver' => 'api',
      
  2. Disabled Logging

    • Temporarily disable for performance:
      activity()->disableLogging();
      // ... critical operation ...
      activity()->enableLogging();
      
  3. Log Name Scoping

    • Use different log names for different purposes:
      activity('security')->log('Failed login attempt');
      activity('audit')->log('User accessed settings');
      

Extension Points

  1. Custom Log Actions

    // app/Actions/CustomLogAction.php
    use Spatie\Activitylog\Actions\LogActivityAction;
    
    class CustomLogAction extends LogActivityAction
    {
        protected function getDefaultDescription(): string
        {
            return 'Custom default description';
        }
    }
    
    // Update config
    'actions' => [
        'log_activity' => \App\Actions\CustomLogAction::class,
    ],
    
  2. Activity Model Observers

    // app/Observers/ActivityObserver.php
    use Spatie\Activitylog\Models\Activity;
    
    class ActivityObserver
    {
        public function saving(Activity $activity)
        {
            if ($activity->description === 'created') {
                $activity->description = 'New record created';
            }
        }
    }
    
    // Register in AppServiceProvider
    Activity::observe(ActivityObserver::class);
    
  3. Custom Activity Attributes

    // Add custom columns to activity_log table
    Schema::table('activity_log', function (Blueprint $table) {
        $table->string('ip_address')->nullable();
        $table->string('user_agent')->nullable();
    });
    
    // Update Activity model
    class Activity extends BaseActivity
    {
        protected $fillable = ['ip_address', 'user_agent'];
    }
    
    // Log additional data
    activity()->withProperties([
        'ip' => request()->ip(),
        'user_agent' => request()->userAgent(),
    ])->log('Action performed');
    

Performance Optimization

  1. Batch Insertion
    // For bulk operations
    \Spatie\Activitylog\Facades\Activity::disableLogging();
    // ... bulk operations ...
    \Spatie\Activitylog\Facades\Activity::enableLogging();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport