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.
## 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
audits table.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;
}
First Use Case:
audits table.$user = User::find(1);
$user->name = "Updated Name";
$user->save(); // Audit log created
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.Auditing Model Changes:
Auditable trait on Eloquent models to log changes automatically.Post model:
class Post extends Model implements AuditableContract
{
use AuditingTrait;
protected $auditEvents = ['created', 'updated', 'deleted'];
}
$auditEvents.Querying Audit Logs:
$audits = User::find(1)->audits()->get();
$audits = User::find(1)->audits()->where('event', 'updated')->get();
$audits = User::find(1)->audits()->with('auditable')->get();
Dynamic Attribute Handling:
class User extends Model
{
use AuditingTrait;
protected $auditExclude = ['password', 'remember_token'];
}
resolveAttribute() to customize how attributes are stored:
public function resolveAttribute($key, $value)
{
return $key === 'email' ? strtolower($value) : $value;
}
Resolvers for Metadata:
config/auditing.php:
'resolvers' => [
'user' => \App\Services\CustomUserResolver::class,
],
UserResolver contract:
use OwenIt\Auditing\Contracts\UserResolver;
class CustomUserResolver implements UserResolver
{
public function resolve()
{
return auth()->user() ?: null;
}
}
Tagging Audits:
$user->setAuditTags(['admin_action']);
$user->name = "Updated by Admin";
$user->save();
$audits = User::find(1)->audits()->where('tags', 'like', '%admin_action%')->get();
Pruning Old Audits:
prune command to clean up old audit logs:
php artisan audit:prune --days=30
DatabaseDriver or using a custom driver.public function handle(Audited $event)
{
// Send notification or log to external service
}
$this->withoutAuditing(function () {
$user = User::create([...]);
});
Performance Overhead:
User::withoutAuditing(function () {
User::update([...]);
});
Attribute Exclusion:
password, api_token) can expose data.$auditExclude in models or the global exclude config.User Resolution:
auth()->user() returns null), audits may lack user context.public function resolve()
{
return auth()->check() ? auth()->user() : null;
}
Morph Maps:
morphMap is configured correctly to avoid ModelNotFoundException in audits.DateTime Handling:
updated_at is handled correctly in the audits table.Listener Conflicts:
retrieved or retrieving events to ensure consistency.Missing Audits:
config/auditing.php enabled: true).AuditableContract and uses AuditingTrait.audits table exists and has the correct schema.Incorrect Attribute Values:
resolveAttribute() to debug or transform values:
public function resolveAttribute($key, $value)
{
if ($key === 'problematic_field') {
logger()->debug("Resolving $key: $value");
}
return $value;
}
Resolver Issues:
$resolver = app(\OwenIt\Auditing\Resolvers\UserResolver::class);
$user = $resolver->resolve();
Pruning Failures:
audits table has an updated_at column (added in v4.1.0).Custom Drivers:
OwenIt\Auditing\Drivers\DatabaseDriver to store audits in a custom location (e.g., Elasticsearch, Redis).$this->app->bind(
\OwenIt\Auditing\Contracts\AuditDriver::class,
\App\Drivers\CustomAuditDriver::class
);
Dynamic Resolvers:
'resolvers' => [
'ip' => [
'enabled' => env('AUDIT_IP_ENABLED', true),
'class' => \OwenIt\Auditing\Resolvers\IpAddressResolver::class,
],
],
Attribute Redaction:
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;
}
}
$this->app->bind(
\OwenIt\Auditing\Contracts\AttributeRedactor::class,
\App\Services\CustomRedactor::class
);
Audit Events:
AuditableContract:
public function getAuditEvents()
{
return ['created', 'updated', 'deleted', 'custom_event'];
}
How can I help you explore Laravel packages today?