tejadong/auditor-bundle
Auditor Bundle brings audit logging to Laravel/PHP applications, recording model changes and user actions so you can trace who changed what and when. Easy to install and configure, it keeps a searchable history of activity for compliance, debugging, and accountability.
This release (5.2.6) is a reference/identity update: the package's repository, composer.json name, and internal references now point at tejadong/auditor rather than the previous location. Treat this as a packaging change first and a feature change second — nothing in the note suggests behavioural changes, but it does mean the strings you copy into composer.json, the vendor path under vendor/, and any hard-coded namespace references in your own code may need to move with it.
Minimal steps to get productive:
composer show | grep -i audit and compare the reported package name against tejadong/auditor. If you are still on the old name, the first decision is whether to migrate now or pin — see Gotchas.vendor/tejadong/auditor/composer.json (for autoload.psr-4 and extra.laravel.providers) and the config/ and database/migrations/ directories. The PSR-4 root is the authoritative answer to "what namespace do I import?" — do not assume it matches the vendor name.php artisan vendor:publish --provider="...\AuditorServiceProvider" (copy the FQCN from the package's composer.json). The config file is effectively the package's documentation: it tells you the table name, the model used for storage, which guards/user resolver is consulted, and whether writes are queued.Subscription being upgraded. Do this on a throwaway branch against a local DB before touching User, because auditing User tends to cascade into auth events and login noise on day one.php artisan tinker and inspect rows on the audit table filtered by auditable_type/auditable_id. Understanding the shape of a stored row (old vs. new values, event name, actor, timestamp, request metadata) determines almost everything you build afterwards.Trait-on-the-model is the primary integration point. For each model you care about, add the audit trait and declare which events matter (created, updated, deleted, restored) plus an $auditExclude/$auditAttributes-style allow-list. Being deliberate here is the difference between a usable trail and a table that grows 40× faster than your domain data.
Two-tier auditing: automatic and semantic. Automatic model-event capture gives you forensic completeness. Layer explicit, named domain events on top for the things humans actually search for — subscription.upgraded, invoice.voided, role.assigned — carrying a small, intentional payload. Your support team reads the latter; auditors and incident response read the former.
Actor resolution is the integration you'll spend the most time on. Determine how the package resolves "who": typically the authenticated guard, with an override for console commands, queued jobs, and impersonation. Wire a middleware or Auth::viaRemember-style hook so that admin impersonation records both the acting admin and the impersonated user. Get this right early — retrofitting actor context onto historical rows is impossible.
Query it as a read model, not an ORM afterthought. Build a small repository/service around the audit model that exposes: timeline for an entity, timeline for a user, diff between two versions, and filtered search (event, date range, actor). Cache nothing at first — audit tables are append-only and index well — but do add composite indexes on (auditable_type, auditable_id, created_at) and (user_id, created_at) in a separate migration so the package's own migrations stay upgradeable.
Diff presentation belongs in your app. Store raw old/new snapshots; render them through a dedicated Blade component or API resource that handles casts (dates, enums, encrypted attributes) uniformly. Do not let views reach into raw JSON.
Retention as a scheduled job. Define an explicit policy (e.g. 24 months hot, then archive to cold storage) and implement pruning in a queued command. Decide now whether the trail is a compliance artefact — if it is, pruning must be an archived copy, never a delete.
composer.json still requires the old package name, a composer update may resolve to a different or orphaned package. Verify: (a) composer show name, (b) vendor/ directory path, (c) PSR-4 namespace in the shipped composer.json, (d) whether the old name is still published as a metapackage alias. Then check your own use statements, config file name, and any string references in service providers or config/app.php.composer dump-autoload -o then php artisan config:clear && php artisan cache:clear. Don't debug namespaces before ruling these out.vendor:publish --force will overwrite your customisations. Diff the package's stubs against your published copies on every minor bump and hand-merge.Auth::user() is empty in the worker. Serialise the actor ID into the job payload rather than resolving it at execution time.Model::where(...)->update(), imports) bypass model events entirely — no audit record at all. Conversely, mass assignment across thousands of rows via save() will produce thousands of rows. Wrap imports in a single semantic audit event and suppress per-model noise.RefreshDatabase and assert on audit rows directly in your own test helpers — a small assertAudited($model, 'updated') helper pays for itself the first time an observer silently stops firing.How can I help you explore Laravel packages today?