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 an easy API. Manually record actions or automatically log Eloquent events, attach subjects/causers and custom properties, and query everything via the Activity model stored 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 performed an action');
    
  3. Querying Logs:

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

First Use Case: Audit Trail for Admin Panel

  • Log model events (e.g., created, updated, deleted) automatically.
  • Example for a Post model:
    use Spatie\Activitylog\Traits\LogsActivity;
    
    class Post extends Model
    {
        use LogsActivity;
    }
    
    Now, every save() or delete() on Post will log an activity.

Implementation Patterns

Core Workflows

1. Manual Logging

  • Basic:
    Activity::log('User {user} created a post', ['user' => $user->name]);
    
  • With Subject/Causer:
    Activity::log('Post updated')
        ->performedOn($post)
        ->causedBy($user)
        ->withProperties(['old_title' => $post->previous('title')]);
    

2. Automatic Model Logging

  • Traits:
    use Spatie\Activitylog\Traits\LogsActivity;
    
    class Post extends Model
    {
        use LogsActivity;
    
        protected static $logAttributes = ['title', 'content'];
        protected static $logOnly = ['title']; // Log only these attributes
        protected static $logName = 'post';    // Custom log name
    }
    
  • Events:
    // Logs 'created', 'updated', 'deleted' by default
    // Override with:
    protected static $logOnlyEvents = ['created', 'updated'];
    

3. Batch Logging

  • Log multiple activities in a single transaction:
    Activity::batch(function () {
        Activity::log('Action 1');
        Activity::log('Action 2');
    });
    

4. Querying Logs

  • Filter by Subject/Causer:
    $userActivities = Activity::whereSubjectType(Post::class)
        ->whereSubjectId($postId)
        ->whereCauserType(User::class)
        ->whereCauserId($userId)
        ->get();
    
  • Property-Based Filtering:
    $activities = Activity::wherePropertiesLike('status', 'pending')->get();
    

5. Customizing Logs

  • Modify Description:
    Activity::useDescriptionForEvent('creating', function ($model) {
        return "{$model->name} is being created";
    });
    
  • Custom Properties:
    Activity::usePropertiesForEvent('updating', function ($model) {
        return ['ip' => request()->ip()];
    });
    

Integration Tips

Middleware for Automatic Logging

  • Log user actions globally:
    namespace App\Http\Middleware;
    
    use Closure;
    use Spatie\Activitylog\Facades\Activity;
    
    class LogUserActivity
    {
        public function handle($request, Closure $next)
        {
            $response = $next($request);
            Activity::log("User accessed {$request->path()}");
            return $response;
        }
    }
    
  • Register in app/Http/Kernel.php:
    protected $middleware = [
        \App\Http\Middleware\LogUserActivity::class,
    ];
    

Queueing Logs for Performance

  • Offload logging to a queue:
    Activity::shouldQueueLogs();
    
  • Process logs later:
    php artisan queue:work
    

Soft Deletes Support

  • Enable soft deletes for logs:
    use Illuminate\Database\Eloquent\SoftDeletes;
    
    class Activity extends \Spatie\Activitylog\Models\Activity
    {
        use SoftDeletes;
    }
    
  • Add deleted_at to migration and config.

Gotchas and Tips

Pitfalls

  1. Performance with Large Logs:

    • Avoid querying all logs at once. Use pagination:
      Activity::latest()->paginate(20);
      
    • Solution: Implement cleanup via Activity::cleanup() or a scheduled job:
      Activity::cleanup()->olderThan(30); // Delete logs older than 30 days
      
  2. Circular References in Properties:

    • Serializing Eloquent models with circular references (e.g., User has posts, posts has user) can cause errors.
    • Solution: Use ->toArray() or exclude problematic relations:
      Activity::withProperties(['user' => $user->toArray()]);
      
  3. Model Events Not Triggering:

    • Ensure LogsActivity trait is used before HasFactory or other traits that might override boot().
    • Debug: Check if registerActivitylogMacro() is called in the model’s boot() method.
  4. UUID vs Integer IDs:

    • Default migration assumes integer IDs. For UUIDs:
      Schema::table('activity_log', function (Blueprint $table) {
          $table->uuid('subject_id')->change();
          $table->uuid('causer_id')->change();
      });
      
  5. Queue Listener Issues:

    • If using queues, ensure the Activity facade is available in the queue worker’s context.
    • Fix: Bind the facade in AppServiceProvider:
      $this->app->bind(\Spatie\Activitylog\Facades\Activity::class, function () {
          return new \Spatie\Activitylog\Facades\Activity();
      });
      

Debugging Tips

  1. Log Format Issues:

    • Check the description and properties in the database. Use dd() to inspect:
      dd(Activity::all()->last()->toArray());
      
  2. Missing Logs:

    • Verify LogsActivity is used and events are not overridden. Add a dd() in the trait’s logActivity() method to debug.
  3. Property Serialization:

    • If properties are null, ensure they are serializable. Use json_encode() to test:
      $properties = ['key' => $value];
      if (json_encode($properties) === false) {
          throw new \Exception("Invalid properties: " . print_r($properties, true));
      }
      

Extension Points

  1. Custom Log Tables:

    • Override the default table name in config:
      'table_name' => 'custom_activity_logs',
      
    • Or dynamically:
      Activity::setTableName('custom_table');
      
  2. Custom Activity Model:

    • Extend the Activity model:
      namespace App\Models;
      
      use Spatie\Activitylog\Models\Activity as BaseActivity;
      
      class Activity extends BaseActivity
      {
          protected $casts = [
              'properties' => 'array',
          ];
      }
      
  3. Event-Based Logging:

    • Listen to custom events:
      use Spatie\Activitylog\Events\ActivityLogged;
      
      Event::listen(ActivityLogged::class, function ($activity) {
          // Custom logic (e.g., send notification)
      });
      
  4. Activitylog Macros:

    • Add custom query scopes:
      \Spatie\Activitylog\Models\Activity::macro('forAdmin', function () {
          return $this->where('description', 'like', '%admin%');
      });
      
    • Use in queries:
      Activity::forAdmin()->get();
      
  5. Logging API Requests:

    • Combine with spatie/laravel-http-middlewares for HTTP activity logging:
      Activity::log("API Request: {$request->method()} {$request->path()}")
          ->withProperties([
              'ip' => $request->ip(),
              'user_agent' => $request->userAgent(),
          ]);
      

Configuration Quirks

  1. logOnly vs logAttributes:

    • logOnly: Logs only these attributes (exclusive).
    • logAttributes: Logs these and all other changed attributes (inclusive).
  2. logName:

    • Overrides the default log name (e.g., post instead of App\Models\Post).
  3. logUnguarded:

    • Logs activities even if mass assignment is guarded:
      protected static $logUnguarded = true;
      
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai