egough / holocron
A Laravel package for recording and querying historical events across your application.
Requires
- php: ^8.2
- illuminate/database: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
- laravel/pint: dev-main
- orchestra/testbench: ^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.5|^11.0|^12.0
README
Polymorphic history recording and activity timeline for Laravel.
Combines audit-style field diffing with human-readable event logging — so you can track both low-level attribute changes and meaningful business events in a single, consistent history record.
Quick Example
// Record a manual event Holocron::record('status_changed') ->on($order) ->by(auth()->user()) ->message('Order marked as paid') ->withMeta(['from' => 'pending', 'to' => 'paid']) ->save(); // Automatic tracking via model trait class Order extends Model { use HasHistory; protected array $holocronTrack = ['status', 'total']; } // Query the timeline $order->history()->latest('recorded_at')->get(); $order->holocronTimeline();
When Should I Use This Package?
Use Holocron when your application needs a persistent, queryable record of what happened, who did it, and what changed.
Typical use cases:
- Order or payment lifecycle tracking
- Content moderation and editorial history
- Support ticket and case notes
- User account activity logs
- Audit trails for compliance
When Not to Use It
Holocron is not a debugging or error-tracking tool. For application exceptions and performance monitoring, consider something like Flare or Sentry.
If you only need simple model diffing without human-readable events, a lightweight audit package may be a better fit. Holocron is designed for applications where both matter.
Installation
composer require egough/holocron
Publish the config and migrations:
php artisan vendor:publish --tag=holocron-config php artisan vendor:publish --tag=holocron-migrations php artisan migrate
Manual Recording
Use the Holocron facade or helper to record events anywhere in your application.
use Egough\Holocron\Facades\Holocron; Holocron::record('note_added') ->on($ticket) ->by(auth()->user()) ->message('Support note added by agent') ->category('communication') ->save();
Record explicit attribute diffs:
Holocron::record('updated') ->on($post) ->by($user) ->withChanges([ 'title' => ['old' => 'Old Title', 'new' => 'New Title'], ]) ->message('Post title updated') ->save();
Attach arbitrary metadata:
Holocron::record('invoice_resent') ->on($invoice) ->by($user) ->withMeta(['recipient' => 'billing@example.com']) ->save();
Model Integration
Add the HasHistory trait to any Eloquent model to enable automatic and on-demand history recording.
use Egough\Holocron\Concerns\HasHistory; use Illuminate\Database\Eloquent\Model; class Order extends Model { use HasHistory; protected array $holocronTrack = ['status', 'total']; }
Automatic Events
The trait automatically records created, updated, deleted, and restored events. For updates, tracked field diffs are stored as:
{
"status": {
"old": "draft",
"new": "active"
}
}
Control which events are recorded per model:
protected array $holocronEvents = ['created', 'deleted'];
Querying History
$order->history; $order->history()->latest('recorded_at')->get(); $order->latestHistory()->get(); $order->holocronTimeline();
Recording from the Model
$project->recordHistory( event: 'archived', message: 'Project archived by admin', actor: auth()->user(), );
Querying
The HolocronEntry model includes helpful query scopes.
use Egough\Holocron\Models\HolocronEntry; // Filter by subject and event type HolocronEntry::query() ->forSubject($order) ->event('status_changed') ->latest('recorded_at') ->get(); // Filter by actor and category HolocronEntry::query() ->causedBy($user) ->category('communication') ->get();
Configuration
The published config file gives you control over table naming, automatic event recording, excluded attributes, and actor resolution.
return [ 'table_name' => 'holocron_entries', 'auto_record' => [ 'created' => true, 'updated' => true, 'deleted' => true, 'restored' => true, ], 'exclude' => [ 'created_at', 'updated_at', ], 'actor_resolver' => static fn () => auth()->user(), ];
Testing
Install development dependencies:
composer install
Run the test suite:
composer test
Or run PHPUnit directly:
vendor/bin/phpunit
Tests use an in-memory SQLite setup — no external database required.
Requirements
- PHP 8.2+
- Laravel 11, 12, or 13
License
MIT