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 Laravel Eloquent models with minimal setup. Laravel Auditing stores a history of model events and attribute diffs, helping detect anomalies and providing easy access to audit logs for display, reporting, and investigation.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require owen-it/laravel-auditing
   php artisan vendor:publish --provider="OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"
   php artisan migrate
  • Publishes migrations and config files. Run migrations to create the audits table.
  1. Enable Auditing on a Model: Use the Auditable trait in your Eloquent model:

    use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
    use OwenIt\Auditing\AuditingTrait;
    
    class User extends Model implements AuditableContract
    {
        use AuditingTrait;
    }
    
    • This automatically logs changes to the model.
  2. First Use Case:

    • Create/update a model instance. The package will log changes to the audits table.
    • Example:
      $user = User::find(1);
      $user->name = "Updated Name";
      $user->save(); // Audit log created
      

Key Configuration

  • Review config/auditing.php for:
    • audit_events: Define which Eloquent events to audit (e.g., ['created', 'updated', 'deleted']).
    • exclude: Globally exclude attributes (e.g., ['password', 'api_token']).
    • resolvers: Customize how metadata (e.g., IP, user agent) is resolved.

Implementation Patterns

Core Workflows

  1. Auditing Model Changes:

    • Use the Auditable trait on Eloquent models to log changes automatically.
    • Example for a Post model:
      class Post extends Model implements AuditableContract
      {
          use AuditingTrait;
      
          protected $auditEvents = ['created', 'updated', 'deleted'];
      }
      
    • Customize events per model by overriding $auditEvents.
  2. Querying Audit Logs:

    • Retrieve audit logs for a model:
      $audits = User::find(1)->audits()->get();
      
    • Filter by event type:
      $audits = User::find(1)->audits()->where('event', 'updated')->get();
      
    • Use relationships to access the original model:
      $audits = User::find(1)->audits()->with('auditable')->get();
      
  3. Dynamic Attribute Handling:

    • Exclude sensitive attributes globally or per model:
      class User extends Model
      {
          use AuditingTrait;
      
          protected $auditExclude = ['password', 'remember_token'];
      }
      
    • Use resolveAttribute() to customize how attributes are stored:
      public function resolveAttribute($key, $value)
      {
          return $key === 'email' ? strtolower($value) : $value;
      }
      
  4. Resolvers for Metadata:

    • Customize how metadata (e.g., IP, user agent) is resolved via resolvers.
    • Example: Override the user resolver in config/auditing.php:
      'resolvers' => [
          'user' => \App\Services\CustomUserResolver::class,
      ],
      
    • Implement the UserResolver contract:
      use OwenIt\Auditing\Contracts\UserResolver;
      
      class CustomUserResolver implements UserResolver
      {
          public function resolve()
          {
              return auth()->user() ?: null;
          }
      }
      
  5. Tagging Audits:

    • Tag audits for categorization:
      $user->setAuditTags(['admin_action']);
      $user->name = "Updated by Admin";
      $user->save();
      
    • Query tagged audits:
      $audits = User::find(1)->audits()->where('tags', 'like', '%admin_action%')->get();
      
  6. Pruning Old Audits:

    • Use the prune command to clean up old audit logs:
      php artisan audit:prune --days=30
      
    • Customize pruning logic by extending the DatabaseDriver or using a custom driver.

Integration Tips

  • APIs: Use audit logs to track changes in API responses or admin panels.
  • Admin Panels: Display audit logs in a dedicated section (e.g., using Laravel Nova or Filament).
  • Event Listeners: Trigger custom logic when audits are created:
    public function handle(Audited $event)
    {
        // Send notification or log to external service
    }
    
  • Testing: Mock audit logs in tests:
    $this->withoutAuditing(function () {
        $user = User::create([...]);
    });
    

Gotchas and Tips

Common Pitfalls

  1. Performance Overhead:

    • Auditing adds database writes for every change. For high-frequency models, consider:
      • Disabling auditing for bulk operations:
        User::withoutAuditing(function () {
            User::update([...]);
        });
        
      • Using a queue for audit logging (though queue support was removed in v4.0.0, consider a custom driver).
  2. Attribute Exclusion:

    • Forgetting to exclude sensitive attributes (e.g., password, api_token) can expose data.
    • Use $auditExclude in models or the global exclude config.
  3. User Resolution:

    • If the user resolver fails (e.g., auth()->user() returns null), audits may lack user context.
    • Ensure resolvers handle edge cases:
      public function resolve()
      {
          return auth()->check() ? auth()->user() : null;
      }
      
  4. Morph Maps:

    • When using polymorphic relationships, ensure the morphMap is configured correctly to avoid ModelNotFoundException in audits.
  5. DateTime Handling:

    • Custom date formats in models may cause issues. Ensure updated_at is handled correctly in the audits table.
  6. Listener Conflicts:

    • If other listeners modify model attributes before auditing, use retrieved or retrieving events to ensure consistency.

Debugging Tips

  1. Missing Audits:

    • Check if auditing is enabled globally (config/auditing.php enabled: true).
    • Verify the model implements AuditableContract and uses AuditingTrait.
    • Ensure the audits table exists and has the correct schema.
  2. Incorrect Attribute Values:

    • Override resolveAttribute() to debug or transform values:
      public function resolveAttribute($key, $value)
      {
          if ($key === 'problematic_field') {
              logger()->debug("Resolving $key: $value");
          }
          return $value;
      }
      
  3. Resolver Issues:

    • Test resolvers in isolation:
      $resolver = app(\OwenIt\Auditing\Resolvers\UserResolver::class);
      $user = $resolver->resolve();
      
  4. Pruning Failures:

    • Check database permissions and ensure the audits table has an updated_at column (added in v4.1.0).

Extension Points

  1. Custom Drivers:

    • Extend OwenIt\Auditing\Drivers\DatabaseDriver to store audits in a custom location (e.g., Elasticsearch, Redis).
    • Bind the driver in the service provider:
      $this->app->bind(
          \OwenIt\Auditing\Contracts\AuditDriver::class,
          \App\Drivers\CustomAuditDriver::class
      );
      
  2. Dynamic Resolvers:

    • Disable/enable resolvers dynamically via config:
      'resolvers' => [
          'ip' => [
              'enabled' => env('AUDIT_IP_ENABLED', true),
              'class' => \OwenIt\Auditing\Resolvers\IpAddressResolver::class,
          ],
      ],
      
  3. Attribute Redaction:

    • Use AttributeRedactor to mask sensitive data in audit logs:
      use OwenIt\Auditing\Contracts\AttributeRedactor;
      
      class CustomRedactor implements AttributeRedactor
      {
          public function redact($attribute, $value)
          {
              return $attribute === 'password' ? '*****' : $value;
          }
      }
      
    • Bind the redactor in the service provider:
      $this->app->bind(
          \OwenIt\Auditing\Contracts\AttributeRedactor::class,
          \App\Services\CustomRedactor::class
      );
      
  4. Audit Events:

    • Extend audit events by implementing AuditableContract:
      public function getAuditEvents()
      {
          return ['created', 'updated', 'deleted', 'custom_event'];
      }
      
    • Handle custom events in the model:
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