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 Auditing Laravel Package

owen-it/laravel-auditing

Track and review changes to your Eloquent models with minimal setup. Laravel Auditing stores a history of updates, helps spot discrepancies or suspicious activity, and makes it easy to retrieve and display audit records in your Laravel app.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require owen-it/laravel-auditing
    

    Publish the migration and config:

    php artisan vendor:publish --provider="OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"
    php artisan vendor:publish --provider="OwenIt\Auditing\AuditingServiceProvider" --tag="config"
    

    Run the migration:

    php artisan migrate
    
  2. Enable Auditing for a Model: Use the Auditable trait in your Eloquent model:

    use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
    use OwenIt\Auditing\Traits\Auditable;
    
    class User extends Model implements AuditableContract
    {
        use Auditable;
    }
    
  3. First Use Case: Trigger an update on a model to generate an audit log:

    $user = User::find(1);
    $user->name = 'Updated Name';
    $user->save(); // Audit log created automatically
    
  4. Retrieve Audit Logs:

    $audits = $user->audits; // Collection of Audit models
    $audits->each(function ($audit) {
        echo $audit->created_at->diffForHumans();
        echo $audit->getOldValues()->toJson();
    });
    

Implementation Patterns

Core Workflows

1. Model-Level Auditing

  • Enable Auditing:
    class Post extends Model implements AuditableContract
    {
        use Auditable;
    }
    
  • Customize Events: Override getAuditEvents() to specify which events to audit:
    public function getAuditEvents()
    {
        return ['created', 'updated', 'deleted'];
    }
    

2. Dynamic Attribute Exclusion

  • Exclude sensitive fields globally in config/auditing.php:
    'exclude' => [
        'password',
        'api_token',
    ],
    
  • Or per-model:
    protected $auditExclude = ['secret_key'];
    

3. Resolver Integration

  • User Resolver: Automatically log the user who made changes. Configure in config/auditing.php:
    'user_resolver' => \OwenIt\Auditing\Resolvers\UserResolver::class,
    
  • Custom Resolvers: Extend OwenIt\Auditing\Contracts\Resolver:
    class CustomResolver implements Resolver
    {
        public function resolve()
        {
            return request()->ip();
        }
    }
    
    Register in config:
    'resolvers' => [
        'ip' => \App\Resolvers\CustomResolver::class,
    ],
    

4. Querying Audits

  • Filter by Event:
    $user->audits()->where('event', 'updated')->get();
    
  • Filter by Changes:
    $user->audits()->whereHas('changes', function ($query) {
        $query->where('key', 'name');
    })->get();
    

5. Multi-User Auditing

  • Enable in config/auditing.php:
    'multi_user' => true,
    
  • Use setAuditUser() manually:
    $user->setAuditUser($adminUser);
    $user->name = 'Updated by Admin';
    $user->save();
    

6. Tagging Audits

  • Add tags to audits:
    $user->auditTag('admin_action');
    $user->name = 'Updated';
    $user->save();
    
  • Query by tag:
    $user->audits()->where('tags', 'like', '%admin_action%')->get();
    

Integration Tips

1. Middleware for Admin Actions

Automatically tag audits for admin actions:

class AdminAuditMiddleware
{
    public function handle($request, Closure $next)
    {
        if (auth()->user()->isAdmin()) {
            $request->auditTag = 'admin_action';
        }
        return $next($request);
    }
}

Use in AppServiceProvider:

public function boot()
{
    $this->app['request']->offsetSet('auditTag', null);
}

2. Custom Audit Drivers

Extend OwenIt\Auditing\Contracts\AuditDriver for custom storage (e.g., Redis):

class RedisAuditDriver implements AuditDriver
{
    public function log($model, $event, $changes, $old, $new, $user)
    {
        Redis::publish('audit', json_encode(compact('model', 'event', 'changes', 'old', 'new', 'user')));
    }
}

Register in config/auditing.php:

'driver' => \App\Drivers\RedisAuditDriver::class,

3. Real-Time Audit Notifications

Use Laravel Echo to broadcast audit events:

class AuditBroadcaster
{
    public function handle($audit)
    {
        broadcast(new AuditEvent($audit))->toOthers();
    }
}

Attach to the audited event:

event(new Audited($audit));

4. API Audit Logging

Log API changes with request details:

class ApiAuditResolver implements Resolver
{
    public function resolve()
    {
        return [
            'ip' => request()->ip(),
            'user_agent' => request()->userAgent(),
            'route' => request()->route()->getName(),
        ];
    }
}

Register in config:

'resolvers' => [
    'api' => \App\Resolvers\ApiAuditResolver::class,
],

5. Soft Deletes Handling

Exclude deleted_at from audits:

protected $auditExclude = ['deleted_at'];

Or globally:

'exclude' => ['deleted_at'],

Gotchas and Tips

Pitfalls

1. Performance Overhead

  • Issue: Auditing every model change can slow down writes.
  • Fix:
    • Disable auditing for non-critical models.
    • Use auditingEnabled() to toggle dynamically:
      if (!$this->auditingEnabled()) {
          return;
      }
      
    • Batch updates to avoid excessive audits.

2. Circular References in Changes

  • Issue: Auditing models with relationships can cause infinite loops if not handled.
  • Fix:
    • Exclude relationships from auditing:
      protected $auditExclude = ['posts'];
      
    • Use resolveChanges() to customize how changes are serialized.

3. Timestamp Conflicts

  • Issue: updated_at conflicts with audit timestamps.
  • Fix:
    • Ensure updated_at is not excluded from audits (it’s included by default).
    • Use getAuditAttributes() to customize audit fields:
      public function getAuditAttributes()
      {
          return array_merge(parent::getAuditAttributes(), ['custom_field']);
      }
      

4. Resolver Failures

  • Issue: Resolvers throwing exceptions can break auditing.
  • Fix:
    • Wrap resolvers in try-catch:
      try {
          $user = $this->userResolver->resolve();
      } catch (\Exception $e) {
          $user = null;
      }
      
    • Use dynamic resolvers to enable/disable them:
      'resolvers' => [
          'user' => [
              'enabled' => env('AUDIT_USER_RESOLVER', true),
              'class' => \OwenIt\Auditing\Resolvers\UserResolver::class,
          ],
      ],
      

5. Mass Assignment Risks

  • Issue: Auditing mass assignments can log sensitive data.
  • Fix:
    • Exclude mass-assignable fields:
      protected $auditExclude = ['password', 'remember_token'];
      
    • Use fillable and guarded to control what gets audited.

6. Morph Map Incompatibilities

  • Issue: Polymorphic relationships may not resolve correctly.
  • Fix:
    • Ensure MorphMap is properly configured in AppServiceProvider:
      public function boot()
      {
          $this->app['router']->morphMap = [
              'post' => \App\Models\Post::class,
              // ...
          ];
      }
      
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