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 Bundle Laravel Package

pbweb/audit-bundle

Symfony bundle for auditing Doctrine entities: it automatically tracks create, update, and delete changes through Doctrine listeners, recording who changed what and when. Configurable storage and a simple API make it easy to review entity change history in your application.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package. Before anything else, internalise that mismatch: a Laravel app will not boot it, config/bundles.php doesn't exist in your app, and there is no service provider to auto-discover. Your realistic entry points are (a) you maintain a Symfony service alongside your Laravel work, (b) you're evaluating audit-trail designs, or (c) you're reusing the underlying Doctrine listener in a Laravel app that already runs Doctrine ORM.

Steps to evaluate:

  1. Read the README, then open composer.json and check the symfony/* version constraints and PHP floor. With 1 star and 0 dependents, expect it to target an older Symfony (3.x/4.x) and to fail on Symfony 6/7 or PHP 8.2+.
  2. Look at src/DependencyInjection/Configuration.php — this is the authoritative source for the config tree. Anything the README says about keys should be verified here.
  3. Look at Resources/config/services.* to see what the bundle actually registers and which tags it applies (typically a doctrine.event_subscriber or doctrine.orm.entity_listener).
  4. Find the listener/subscriber class and read its onFlush/postFlush (or preUpdate/postUpdate) methods. That is the entire behaviour of the bundle.

First use case: audit an entity's create/update/delete into a log table, storing the changed fields plus a user/request context. In Symfony that's composer require pbweb/audit-bundle, register the bundle class in config/bundles.php, add a pbweb_audit: (verify the actual alias) block under config/packages/, and map the entities you want tracked. In Laravel the equivalent first use case is a ModelObserver on created/updated/deleted writing diffs via getDirty() / getOriginal() — or just install owen-it/laravel-auditing, which is the mature, maintained analogue.

Implementation Patterns

The bundle almost certainly follows the standard Doctrine audit pattern, and that pattern is worth understanding regardless of whether you keep the dependency:

  • Subscriber vs. listener. A global subscriber listens to onFlush and walks UnitOfWork::getScheduledEntityInsertions/Updates/Deletions. An entity listener is attached per entity via #[ORM\EntityListeners] and is easier to scope. Prefer the listener for a handful of entities; use the subscriber only when you need blanket coverage.
  • Diff capture. UnitOfWork::getEntityChangeSet($entity) returns [field => [old, new]] for scalar fields only. That's the value you persist — not the entity.
  • Context injection. The audit row needs who and from where. Wire a request-scoped context provider (Symfony: RequestStack; Laravel: Auth::id(), request()->ip()) into the listener, and make it nullable so CLI/queue contexts don't blow up.
  • Transactional consistency. The safe pattern is to write audit rows inside the same flush cycle (onFlush schedules an insert; postFlush commits) so the audit trail can never diverge from the data. The alternative — dispatching to a queue in postFlush — trades consistency for latency; pick deliberately.
  • Scoping. Don't audit everything. Maintain an explicit allowlist of audited entities and ignored fields (updated_at, password_hash, tokens). Ignoring sensitive fields is a security requirement, not a nicety.
  • Laravel translation of the pattern. Model::observe(AuditObserver::class); in updated(), use $model->getChanges() and $model->getOriginal($key); write to an audits table with auditable_type/id, event, old_values, new_values (JSON), user_id, ip. owen-it/laravel-auditing implements exactly this — steal its schema even if you don't use the package.
  • Integration tip. If you're inside a Symfony app and want to extend rather than fork, alias the bundle's storage service in your own services.yaml to point at a custom writer (DB table, PSR-3 logger, or event dispatcher), and decorate the subscriber rather than editing vendor code.

Gotchas and Tips

  • Framework lock-in. There is no path to "just require it" in Laravel. If you're using Doctrine in Laravel (e.g. laravel-doctrine/orm), you can manually instantiate the listener and tag it in your Doctrine config, but you'll be reimplementing the bundle's DI wiring by hand — at which point copying ~100 lines of listener code is cheaper and leaves you with no abandoned dependency.
  • Maintenance risk is the headline. 1 star, 0 dependents, no ecosystem. Check the last commit date, open issues, and CI badge before putting this anywhere near production. Budget for vendoring or replacing it.
  • Flush recursion. Writing audit rows from inside onFlush/postFlush re-enters the UnitOfWork. Guard with a boolean flag or a separate EntityManager; otherwise you get infinite loops or EntityManager is closed.
  • Collection changes are invisible. getEntityChangeSet() will not tell you that a OneToMany/ManyToMany association changed. If association history matters, you need explicit collectionChangeSet handling or separate domain events.
  • Lazy loading in listeners. Touching an uninitialised proxy or collection during the flush can trigger extra queries, and in the worst case a nested flush. Read only scalar fields and already-loaded associations.
  • Deletions are awkward. At postRemove the entity is detached; capture identifiers and a snapshot of the fields you need at preRemove instead.
  • Never persist the entity as the payload. Serialising Doctrine entities directly gives you circular references and proxy artefacts. Normalise to plain scalars/arrays before writing.
  • Config caching. In Symfony, changing bundle config requires bin/console cache:clear; stale container caches produce "unknown option" errors that look like bugs in the bundle.
  • Debugging. bin/console debug:container --tag=doctrine.event_subscriber confirms the subscriber is registered; debug:event-dispatcher shows listeners. If nothing is logged, the tag is usually missing — not the logic.
  • Sensitive data. Audit tables are a common leak vector. Redact password hashes, tokens, and PII at the listener level, and consider column-level encryption for the old_values/new_values payloads.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core