Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Audit Trail Bundle Laravel Package

th3mouk/audit-trail-bundle

A Symfony bundle that automatically logs Doctrine entity changes, recording who created, updated, or deleted records and keeping a searchable history of modifications for compliance, auditing, and debugging.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a pre-1.0 audit trail package (v0.1.2), so treat the API as unstable and pin an exact version in composer.json ("th3mouk/audit-trail-bundle": "0.1.*") rather than floating it.

  1. Install and publish: composer require th3mouk/audit-trail-bundle, then publish the config and migrations (php artisan vendor:publish --tag=...) and run php artisan migrate. The package needs its audit_entries (or equivalently named) table plus a polymorphic link back to your models.
  2. Look first at: the config file (to see which Eloquent events are recorded by default and which columns are captured), the migration (to understand indexing — you'll query this table a lot), and the trait/interface you attach to models.
  3. First use case: attach the audit trait to a single, high-value model (e.g. Invoice or User), perform a create/update/delete, and inspect the generated entries. Confirm that a freshly created model's DB-assigned primary key is present in the create entry — this is exactly the bug fixed in v0.1.2, so verify it on your setup before trusting the trail.

Because it's 0.1.x, skim the trait/interface contracts directly in vendor/ — docs are thin at this stage.

Implementation Patterns

  • Trait-based opt-in per model: add the package trait (and implement whatever interface it requires) only on models that genuinely need auditing. Auditing every model globally is a common foot-gun in this kind of package.
  • Actor context: most audit packages resolve the current user from auth(). Set this explicitly (and null it in console/queue contexts) so background jobs and artisan commands don't record a stale or wrong actor. Wrap this in a small AuditContext service or middleware.
  • Reading history in the UI: expose the polymorphic relationship ($model->auditEntries) and render a timeline. Filter by event type (created/updated/deleted) and eager-load to avoid N+1.
  • Diffing / old-new values: store and diff the old/new JSON payloads in a presenter rather than in the controller. Keep field-label mapping in one place so the UI stays readable.
  • Manual/custom entries: for domain events that aren't plain CRUD (e.g. "status transitioned", "exported report"), use the manual logging entry point instead of faking an update. This keeps the trail semantic.
  • Integration with queued work: since the actor is often lost in queues, pass the acting user id through the job or re-hydrate it in a JobProcessing listener before the job runs.
  • Compliance exports: query the audit table into a dedicated read model / export job if you need immutable, append-only retention — don't let application code mutate entries.

Gotchas and Tips

  • The v0.1.2 fix matters for create entries: previously the create entry didn't reliably carry the database-assigned key (auto-increment/UUID generated by the DB). If you were backfilling or joining audit entries to records by key, upgrade and re-check historical rows — old create entries may be missing the key and won't retroactively gain it.
  • 0.x semver = breaking changes allowed: read every changelog. Pin versions and upgrade deliberately; don't assume patch releases are inert.
  • Bulk operations bypass Eloquent events: Model::where(...)->update(), insert(), upsert, and raw queries won't fire the events the package listens to. Use save()/delete() per model, or log manually, if those changes must be audited.
  • Soft deletes and restores: confirm your config records deleted/restored the way you expect — these are separate events in Laravel and easy to miss.
  • Pivot tables and sync(): many-to-many changes often don't produce useful entries. Decide explicitly whether you need them and handle via manual entries if so.
  • Performance: the audit table grows fast and is write-heavy. Add composite indexes on (auditable_type, auditable_id) and on the event/created-at columns; consider pruning or archiving old entries.
  • Config caching: after changing package config, run php artisan config:clear — a stale cached config is a classic "why isn't it auditing?" cause.
  • Testing: use assertDatabaseHas against the audit table and a fake authenticated user; add a regression test asserting the create entry contains the model's key (the v0.1.2 behaviour) so a future refactor can't silently drop it.
  • Extension points: the config and the manual-logging/resolver hooks are where you customise actor resolution and payload shape; prefer these over subclassing internal classes, which will move in 0.x.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json