wedevelopnl/audit-log
A Laravel package for recording audit trails of your application's data. It logs model events such as create, update, and delete, capturing the changes made, the user responsible, and timestamps, so you can review activity and keep a reliable history of modifications to your Eloquent models.
Install and migrate. composer require wedevelopnl/audit-log, publish the config and migrations (php artisan vendor:publish), then php artisan migrate. The 6.0.0 schema adds indexes on channel, actor_label and subject_label, so existing installs must run the new migrations — don't skip them or reader queries will table-scan.
Where to look first. Read the config file for the default channel and the flush strategy, then skim docs/adr/0010-records-commit-with-the-callers-flush.md — it defines the flush contract that the entire 6.0.0 error-logging behaviour hangs off.
First use case. Record a meaningful business event (e.g. "invoice marked paid") with a subject model and actor, then read it back through RecordReader:
audit()->record(new InvoicePaid($invoice));
app(RecordReader::class)->forSubject($invoice)->latest()->get();
Verify the record appears after a normal request and after a queued job — that confirms flushing is wired to both kernel.terminate and console.terminate.
RecordReader. Centralise queries there rather than hitting the record table directly — it owns the channel / actor_label / subject_label filters and now benefits from the new indexes.AuditEntry::fromRecord($record) when you need to serialise or hand off an audit entry (e.g. queue payloads, notifications) without a live model reference.SubjectLabeller binding when the default label isn't useful for your domain. Note NullSubjectLabeller now lives in Recording, but alias resolution is unchanged, so most apps need no edits.RecordReader::actors() now labels each actor by their most recent record, not the lexicographically greatest label — useful for "last known name" displays, but means renaming a user retroactively changes their historical actor label in that list.kernel.terminate / console.terminate when records were recorded but never flushed. If you see those errors, you're recording after the flush point (e.g. in destructors, finally blocks, or queued terminated callbacks) — move the record earlier or flush explicitly.FieldChange, RenderLine parameters, and event data reject NAN, INF, and invalid UTF-8 when built/recorded. This is a fix — previously the flush failed and rolled back your audited change — but it's a behaviour change: sanitise values (cast floats, mb_convert_encoding/json_encode guard) before constructing the event, or you'll now fail fast in your domain code.NullSubjectLabeller moved from Infrastructure\Symfony to Recording. Only direct class references break; keep using the SubjectLabeller interface/alias in your app.RecordReader so your queries use the new indexes; ad-hoc where chains on unindexed columns will feel slow on large audit tables.SubjectLabeller container binding, and AuditEntry::fromRecord() are the intended seams — prefer them over subclassing records or reader internals.How can I help you explore Laravel packages today?