How to Create Audit Logs in Laravel (Step-by-Step Guide)
Audit logs are essential for tracking user activity, debugging issues, and maintaining security in your Laravel application. In this guide, you'll learn how to build a scalable and production-ready audit log system.
📌 What is an Audit Log?
An audit log records actions performed in your system such as:
- Who performed the action
- What was changed
- When it happened
- From where (IP address)
🛠 Step 1: Create Audit Log Table
Schema::create('audit_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable();
$table->string('event');
$table->string('model_type');
$table->unsignedBigInteger('model_id');
$table->json('old_values')->nullable();
$table->json('new_values')->nullable();
$table->ipAddress('ip_address')->nullable();
$table->text('user_agent')->nullable();
$table->timestamps();
});
Using JSON fields allows you to store flexible before/after changes.
⚙️ Step 2: Create AuditLog Model
php artisan make:model AuditLog
class AuditLog extends Model
{
protected $fillable = [
'user_id',
'event',
'model_type',
'model_id',
'old_values',
'new_values',
'ip_address',
'user_agent'
];
protected $casts = [
'old_values' => 'array',
'new_values' => 'array',
];
}
🔁 Step 3: Create Auditable Trait
trait Auditable
{
public static function bootAuditable()
{
static::created(function ($model) {
self::logEvent($model, 'created');
});
static::updated(function ($model) {
self::logEvent($model, 'updated');
});
static::deleted(function ($model) {
self::logEvent($model, 'deleted');
});
}
protected static function logEvent($model, $event)
{
AuditLog::create([
'user_id' => auth()->id(),
'event' => $event,
'model_type' => get_class($model),
'model_id' => $model->id,
'old_values' => $model->getOriginal(),
'new_values' => $model->getAttributes(),
'ip_address' => request()->ip(),
'user_agent' => request()->userAgent(),
]);
}
}
🧩 Step 4: Use Trait in Model
class Order extends Model
{
use Auditable;
}
Now all create, update, and delete operations will be logged automatically.
🚀 Step 5: Optimize with Queue
dispatch(function () use ($data) {
AuditLog::create($data);
})->onQueue('logs');
This ensures your application remains fast by processing logs in the background.
🔍 Step 6: Log Only Changed Fields
$changes = $model->getChanges();
AuditLog::create([
'old_values' => array_intersect_key($model->getOriginal(), $changes),
'new_values' => $changes,
]);
This keeps your logs clean and reduces storage usage.
⚠️ Common Mistakes
- Logging everything without filtering
- Not using queues
- Storing unnecessary data
- No indexing on database
🎯 Conclusion
A well-designed audit log system improves debugging, security, and transparency in your Laravel application. By using model events, traits, and queues, you can build a scalable solution suitable for production.