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

Auditor Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. Confirm what you actually have installed. Run 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.
  2. Read the package's own scaffolding before your app code. Open 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.
  3. Publish and read the config. 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.
  4. First use case: attach the trait to one model and log a single meaningful domain event — e.g. a 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.
  5. Verify by querying, not by trusting the UI. 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.

Implementation Patterns

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.

Gotchas and Tips

  • The rename is the headline risk. If your 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.
  • Class-not-found after upgrade is almost always an autoload or config cache issue: composer dump-autoload -o then php artisan config:clear && php artisan cache:clear. Don't debug namespaces before ruling these out.
  • Published files do not update themselves. Config and migrations you published are now yours. vendor:publish --force will overwrite your customisations. Diff the package's stubs against your published copies on every minor bump and hand-merge.
  • Audit writes inside a transaction roll back with it. That is usually correct, but it means failed operations leave no trace. If you need "attempted and rejected" records, write those explicitly outside the transaction (or on a separate connection).
  • Infinite recursion. Auditing the audit model itself, or auditing a model that is touched by an observer during the audit write, produces a loop. Exclude the storage model explicitly and guard observers that mutate audited models.
  • Queued audits lose context. If writes are queued, Auth::user() is empty in the worker. Serialise the actor ID into the job payload rather than resolving it at execution time.
  • Redaction is a config concern, not a per-call concern. Password hashes, tokens, and PII must be stripped by default via the exclude list. Audit one model, dump a row, and read it with an attacker's eyes before shipping.
  • Volume surprises. Bulk operations (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.
  • Extension points worth knowing: the storage model is usually rebindable via config (swap it if you need a custom table or multi-tenant partitioning), and the resolver for actor/timestamp/request is typically a container binding or config closure. Both are cleaner than forking.
  • Test it like a feature. Use 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.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route