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

Symfony Doctrine Audit Laravel Package

precision-soft/symfony-doctrine-audit

Symfony Doctrine Audit provides automatic audit trails for Doctrine entities in Symfony apps. It tracks create, update, and delete operations, records changed fields and values, and stores a history for compliance, debugging, and accountability, with configurable listeners and mappings.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. v4.1.0 is a Doctrine ORM bundle, not a Laravel-native package. Everything in the release — onFlush/postFlush hooks, UnitOfWork::isInIdentityMap(), getOriginalEntityData(), Collection::clear() — is Doctrine event-listener surface. That means it fits a Laravel application only where the audited models are Doctrine entities, which is a minority pattern in Laravel codebases. Eloquent-based models get nothing from this release. A TPM should treat this as a Doctrine-infrastructure dependency that happens to be installed via Composer into a Laravel app, not as a Laravel package.

Integration feasibility. Composer-installable and the changes are additive plus bug-fix oriented, so the migration surface is small. The one hard gate is the changed floor: doctrine/dbal now requires ^4.2 because the audit schema uses Types::ENUM and Column::getValues(). Applications on dbal 4.0/4.1 cannot install this release, and applications pinned to 3.x cannot either. Any Laravel app that also runs Doctrine migrations is likely to have a DBAL pin in composer.lock, so the first integration question is not "does the feature work" but "can we resolve the dependency graph."

Technical risk. Three items carry real weight:

  1. Error-timing behaviour change. Identifiers that contain an association are still refused, but the refusal now throws in onFlush before the transaction opens instead of in postFlush after commit. This is a correctness improvement — previously the database kept a committed change with no audit row — but it converts a silent audit gap into a hard write failure. Entities whose primary key includes a foreign key are now the most likely thing to break on upgrade, and they will break in production write paths, not in tests, unless those paths are exercised.
  2. JSONL timestamp semantics. New records write ATOM with offset; old records are still read in the reader's own timezone. This is a mixed-format corpus with two different boundary interpretations, and --before on a purge run now means different things depending on when the record was written. Any retention policy or export pipeline consuming these files needs to know which era a record is from.
  3. Silent-looking fixes that were actually data-loss bugs. Collection clearing and owner removal previously emitted an empty removed list and lost collection history; a failed purge could leave a partial <file>.purge that the next run told the operator to restore over a good audit file; FileStorage could leave a partial JSONL line that then broke every subsequent read. These are reassuring to have fixed, but the fact that they existed means historical audit files produced by earlier releases may contain gaps that the upgrade does not retroactively repair.

Key questions for the maintainers.

  • Is the onFlush refusal for association-keyed identifiers a hard throw, and does it abort the whole unit of work or just that entity?
  • What is the supported upgrade path for dbal 3.x users — is 4.1.x the last line supporting 3.x?
  • Will a future release normalise or rewrite historical JSONL timestamps, or is the mixed-timezone corpus permanent?
  • Is the .example/ micro-kernel intended as a supported reference or as a test fixture?

Integration Approach

Stack fit. Confirm first whether the audit target is Doctrine entities. If the application is Eloquent-only, this package is out of scope and the assessment ends there. If there is a Doctrine island — a reporting module, a legacy bounded context — the bundle is a reasonable fit for that island and nothing else.

Migration path. The upgrade is a composer require bump with three pre-flight checks:

  1. Resolve DBAL first. Run composer why-not doctrine/dbal ^4.2 before touching the bundle. If the app is pinned below 4.2 by a migration tool, a profiler, or a Laravel major that constrains DBAL, either bump those in the same change or defer the bundle upgrade. Do not attempt to satisfy the constraint by ignoring it — the release notes state the declared floor was previously uninstallable, meaning earlier versions may have installed against a DBAL that lacks the enum APIs the schema needs.
  2. Exercise the identity-map paths. Write or locate a test that flushes an entity keyed by a foreign key, and one that clears a collection on an audited owner. These are the two paths with changed behaviour; both are ordinary application operations and both should be covered before deploy.
  3. Re-baseline the audit reader. Any internal tool that parses JSONL must handle ATOM-with-offset alongside the legacy naive format. This is a code change in the consumer, not in the bundle, and it should ship before or with the upgrade, not after.

Compatibility. The bundle remains backward compatible at the API level; there are no removals in this release. The compatibility risks are all behavioural (error timing) and environmental (DBAL floor, mixed timestamp corpus). Semver-wise a DBAL floor bump in a minor is aggressive but defensible given the previous floor could not install.

Sequencing. (1) Bump dbal and any dependents; (2) upgrade the bundle; (3) update JSONL consumers for ATOM offsets; (4) run the .example/ validation harness — ./.dev/validate/all.sh --example — against MySQL and MariaDB to confirm the micro-kernel scenarios pass on your engine and version; (5) deploy with the identifier and collection flush tests as the gate.

Operational Impact

Maintenance. The .example/ application plus its dedicated CI job is a meaningful maintenance asset: it gives an adopter a runnable oracle for expected behaviour across every capability, on two database engines. It also raises the maintenance bar for the maintainer, since the example is now a second thing to keep green. From a consumer standpoint, the addition is low-cost and high-value.

Support. Expect an uptick in two support categories after upgrade: applications whose entities are keyed by associations and now throw at flush, and operators reading a .purge file. The purge behaviour changed in a good direction — an incomplete kept set is now deleted and the real cause reported, rather than being left as a trap — but operators familiar with the old behaviour need to be told that a missing .purge file now means "the purge failed, read the error" rather than "recovery is impossible."

Scaling. The correctness fixes for collection auditing read join rows from the database during onFlush, while they are still present. That is the right fix and there is no other place to do it, but it adds query volume to the flush path proportional to the number of audited owning collections being cleared. On bulk operations — mass deletes, wide collection clears — this is a new per-flush cost in the write path, and it lands precisely where write latency is most sensitive. Benchmark the batch-delete path before and after.

Failure modes to instrument. (a) Flush-time exceptions from association-keyed identifiers aborting ordinary writes; (b) partial .purge removal with the underlying cause only in logs; (c) FileStorage truncation relying on an exclusive lock — correct on a single host, but a shared filesystem or multi-container deployment writing the same JSONL path is outside what a PHP file lock reliably guarantees; (d) cursor rejection, which now correctly refuses an undecodable cursor rather than silently reporting end-of-data — good, but it will surface previously invisible corruption as an error; (e) timezone drift on --before boundaries for records written before this release.

Ramp-up. Low for a developer who has worked with Doctrine events; moderate for a Laravel-only team, because the debugging model is different — failures arrive as onFlush exceptions from a listener rather than as Eloquent model events. Budget half a day for a Doctrine-familiar engineer to read the example app and run the validation script, and add a day if the team must first untangle a DBAL version conflict. The --identity='code="007"' quoting escape hatch is a small usability win worth documenting internally, since the unquoted form silently casts to integer and matches nothing — a class of bug that is hard to spot in a CLI invocation.

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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel