mrtolouei / laravel-audit
A lightweight and framework-native audit log package for Laravel applications.
Requires
- php: ^8.2
- illuminate/database: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^10.0|^11.0
- phpunit/phpunit: ^11.5|^12.0|^13.0
This package is auto-updated.
Last update: 2026-08-19 06:58:54 UTC
README
A lightweight, framework-native audit log package for Laravel applications.
Laravel Audit automatically records Eloquent model changes and stores:
- The model that was changed
- The event that occurred
- Original values
- Changed values
- The authenticated user (causer)
- IP address
- User agent
- Request ID
- Timestamp
The package is designed to stay small, explicit, and Laravel-native without requiring global observers.
Table of Contents
- Requirements
- Installation
- Basic Usage
- How It Works
- Audits Relationship
- Audit Model
- Audit Events
- Pre-Model Events
- Include / Exclude Attributes
- Change Detection
- Causer
- Multiple Authentication Guards
- Manual Causer
- Audit Context
- Manual Audit Context
- Console / Queue Usage
- Testing
- Contributing
- License
Requirements
- PHP 8.2+
- Laravel 11+
- Laravel 12+
- Laravel 13+
Installation
Install the package via Composer:
composer require mrtolouei/laravel-audit
The package automatically registers its service provider through Laravel package discovery.
Publish the configuration:
php artisan vendor:publish --tag=audit-config
Publish the migration:
php artisan vendor:publish --tag=audit-migrations
Run the migration:
php artisan migrate
Basic Usage
Add the Auditable trait to any Eloquent model you want to audit.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use MrTolouei\LaravelAudit\Concerns\Auditable; class User extends Model { use Auditable; }
From this point, the following events are automatically recorded:
created
updated
deleted
restored
No observer registration is required.
How It Works
The package integrates directly with Laravel Eloquent model events through the Auditable trait.
When an auditable model triggers an event:
Eloquent Model Event
|
v
Auditable Trait
|
v
AuditService
|
+---- ChangeDetector
|
+---- CauserResolver
|
+---- AuditContext
|
v
Audit Model
|
v
audits table
Each audit record belongs to the changed model through a polymorphic relationship.
Audits Relationship
Every model using the Auditable trait automatically gets an audits() relationship.
$user->audits;
Get the latest audit:
$user->audits()->latest()->first();
Get all audits:
$user->audits()->latest()->get();
Audit Model
Audit records are represented by:
MrTolouei\LaravelAudit\Models\Audit
The model contains the following information:
| Column | Description |
|---|---|
id |
Audit ID |
subject_type |
Audited model type |
subject_id |
Audited model ID |
event |
Eloquent event |
original_values |
Values before the change |
changed_values |
Values after the change |
causer_type |
Causer model type |
causer_id |
Causer model ID |
ip_address |
Request IP address |
user_agent |
Request user agent |
request_id |
Request/correlation ID |
created_at |
Audit creation time |
updated_at |
Audit update time |
Audit Events
By default, all supported events are recorded:
'events' => [ 'created', 'updated', 'deleted', 'restored', ],
You can change the global default:
'events' => [ 'created', 'updated', ],
Per-Model Events
Each model can override the global event configuration.
class User extends Model { use Auditable; public static function getAuditEvents(): array { return [ 'created', 'updated', ]; } }
This model will only record:
created
updated
The model-level configuration takes precedence over the global configuration.
Include / Exclude Attributes
Laravel Audit allows each model to control which attributes are recorded.
Include
Use getAuditInclude() to explicitly define the attributes that should be audited.
class User extends Model { use Auditable; public function getAuditInclude(): array { return [ 'name', 'email', 'status', ]; } }
Only these attributes will be stored in the audit record.
Exclude
Use getAuditExclude() to exclude specific attributes.
class User extends Model { use Auditable; public function getAuditExclude(): array { return [ 'password', 'remember_token', ]; } }
Excluded attributes will not be stored in the audit record.
Include + Exclude
Both options can be used together.
class User extends Model { use Auditable; public function getAuditInclude(): array { return [ 'name', 'email', 'password', 'status', ]; } public function getAuditExclude(): array { return [ 'password', ]; } }
The final audited attributes are:
name
email
status
Exclude is applied after include.
Change Detection
Laravel Audit records changes according to the event.
Created
For a newly created model:
[
'original_values' => [],
'changed_values' => [
'name' => 'Ali',
'email' => 'ali@example.com',
],
]
Updated
For an updated model:
[
'original_values' => [
'name' => 'Ali',
'email' => 'old@example.com',
],
'changed_values' => [
'name' => 'Alireza',
'email' => 'new@example.com',
],
]
Only changed attributes are recorded.
Deleted
For a deleted model:
[
'original_values' => [
'name' => 'Ali',
'email' => 'ali@example.com',
],
'changed_values' => [],
]
Restored
For a restored model, Laravel Audit records the values involved in the restoration event.
[
'original_values' => [
// previous values
],
'changed_values' => [
// changed values
],
]
Causer
The causer is the model responsible for an audit event.
By default, Laravel Audit resolves the authenticated user from Laravel's default authentication guard.
For example:
auth()->user();
If a user updates another user:
$user->update([ 'name' => 'Alireza', ]);
the audit record contains:
causer_type = App\Models\User causer_id = 123
The audited model and the causer are separate concepts:
subject = model being changed
causer = model responsible for the change
Multiple Authentication Guards
Applications using multiple guards can specify which guard should be used for causer resolution.
For example:
'causer' => [ 'guard' => 'admin', ],
Laravel Audit will then resolve:
auth('admin')->user();
instead of the default guard.
For a member-based application:
'causer' => [ 'guard' => 'member', ],
Manual Causer
The CauserResolver can be used to explicitly specify the causer.
use MrTolouei\LaravelAudit\Support\CauserResolver; $causerResolver = app(CauserResolver::class); $causerResolver->setCauser($admin);
Subsequent audit records will use the manually specified causer.
Clear the manually configured causer:
$causerResolver->clear();
When no manual causer is configured, the resolver falls back to the configured authentication guard.
Audit Context
AuditContext stores request-related information associated with an audit.
It supports:
IP address
User agent
Request ID
During an HTTP request, the context can automatically populate itself from the current request.
$context = app(AuditContext::class); $context->populateFromRequest();
The following values are resolved:
$request->ip(); $request->userAgent(); $request->header('X-Request-ID');
Manual Audit Context
Audit context values can also be configured manually.
use MrTolouei\LaravelAudit\Support\AuditContext; $context = app(AuditContext::class); $context ->setIpAddress('127.0.0.1') ->setUserAgent('My Application') ->setRequestId('request-123');
Manual values take precedence over values automatically resolved from the request.
For example:
$context ->setRequestId('custom-request-id') ->populateFromRequest();
The manually specified request ID will not be overwritten.
This makes the context usable outside normal HTTP requests, including:
- Queue jobs
- Commands
- Scheduled tasks
- Workers
- Console applications
- Background processes
Console / Queue Usage
Laravel Audit does not require an HTTP request.
For example:
$user->update([ 'status' => 'processed', ]);
inside a queue job can still create an audit record.
In such cases:
ip_address = null
user_agent = null
request_id = null
unless these values are explicitly provided through AuditContext.
Testing
Run tests using PHPUnit:
vendor/bin/phpunit
Contributing
- Fork the repository
- Create a feature branch (
feature/awesome-feature) - Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/awesome-feature) - Open a Pull Request
License
This package is open-sourced software licensed under the MIT license.