Looking to hire Laravel developers? Try LaraJobs

laravel-logger maintained by aifst

Description
Logger package for Laravel 5.6 and up
Last update
2026/07/27 19:39 (dev-master)
License
Downloads
100
Tags

Comments
comments powered by Disqus

Laravel Logger

A lightweight audit log for Eloquent models. Add one trait and every create / update / delete is recorded — with the acting user, a before/after diff, and an optional owner (the scope the event happened in, e.g. a project or a site).

Each entry stores:

  • subject — the model the action was performed on (model_type / model_id)
  • actioncreated / updated / deleted
  • user — who caused it (user_id)
  • before / after — the changed attributes (a diff for updates, the full record for create/delete)
  • owner (optional) — the polymorphic scope container the event happened in (owner_type / owner_id), or null for a global entry

Installation

Install via Composer:

composer require "aifst/laravel-logger:^1.0.0"

The service provider is auto-discovered. To register it manually, add it to config/app.php:

'providers' => [
    // ...
    Aifst\Logger\LoggerServiceProvider::class,
];

Publish the migration and config/logger.php, then migrate:

php artisan vendor:publish --provider="Aifst\Logger\LoggerServiceProvider"
php artisan migrate

Usage

Add the Logger trait to any model you want audited:

use Aifst\Logger\Traits\Logger;

class Course extends Model
{
    use Logger;
}

By default all three events are logged. Opt out per model by overriding the flags:

protected static function loggedCreated(): bool  { return true; }
protected static function loggedUpdating(): bool { return true; }
protected static function loggedDeleting(): bool { return false; }

Recording the acting user

The trait does not know your auth layer, so tell it how to resolve the current user id (return null for system/unauthenticated actions):

protected static function loggerUserId()
{
    return auth()->id();
}

Limiting the logged attributes

By default the whole record (minus id / timestamps) is captured. Restrict it to specific columns:

protected static function loggedFields(): ?array
{
    return ['title', 'status'];
}

Owner scope (optional)

A log entry records the subject it happened to. You may also record an owner — the scope container the event happened in (a project, a site, a tenant…). The owner is polymorphic and nullable, so entries can be scoped to a project, to a site, or left global, without tying the log to any single entity — and it is distinct from the subject.

Override loggerOwner() to return the owning model:

protected function loggerOwner()
{
    return $this->project; // or Site::current(), or null for a global entry
}

The entry then stores owner_type / owner_id (honouring a registered morph map).

Querying

The Log model exposes read helpers:

use Aifst\Logger\Models\Log;

// A model's own history (via the Logger trait's relation)
$course->logs()->latest()->get();

// By owner scope (all activity in a project)
Log::forOwner($project)->latest()->get();
Log::forOwner($project->getMorphClass(), $project->id)->get();

// By action
Log::wasCreated()->get();
Log::wasUpdated()->get();
Log::wasDeleted()->get();

// By subject entity
Log::entity($course->getMorphClass(), $course->id)->get();

// In a time window
Log::between($from, $to)->get();

// Reconstruct a model's state at a point in time
$snapshot = $course->logs()->stateOn($datetime);

before and after are returned as arrays (JSON is decoded automatically).

Upgrading an existing install (owner scope)

If your logs table predates the owner columns, add them with a migration:

$table->string('owner_type')->nullable();
$table->unsignedBigInteger('owner_id')->nullable();
$table->index(['owner_type', 'owner_id']);

Existing rows keep a null owner; nothing else changes.

License

MIT.