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.
onFlush/postFlush listener plus a bespoke purge job. This release is largely a catalogue of exactly the bugs that hand-rolled listeners ship with — see below — so the comparison should be "our own listener, two iterations in" not "our own listener, day one."purge command with --before is the retention lever; you can commit to a stated retention window ("24 months hot, then removable") and back it with a tool that refuses to proceed on a corrupt file rather than silently doing the wrong thing.onFlush, before the transaction opens, instead of in postFlush after commit. Previously the database kept a change whose audit row was lost — i.e. silent gaps in the audit log. That is the single most important line in these notes.<file>.purge kept set behind, and a failed JSONL write is truncated under lock. Both previously turned one bad run into a file that every later read and purge rejected.--identity='code="007"' is the escape hatch for zero-padded codes, references and string-that-looks-numeric keys. If your product identifiers are human-readable codes, this decides whether the CLI can target a single entity at all.Consider it when:
owen-it/laravel-auditing or spatie/laravel-activitylog instead.DELETE FROM audit WHERE created_at < ?.Look elsewhere when:
onFlush for collection removals — correctness bought with queries.doctrine/dbal is pinned below ^4.2. This release raises the floor because Types::ENUM and Column::getValues() don't exist in 4.0/4.1 — the previously declared floor could not actually install. If you're stuck on dbal 4.0/4.1, this version is not available to you and the enum-column stability it provides is not either.To executives (one paragraph): We can offer customers a complete, tamper-evident change history — including who was added to or removed from collections — without buying an audit SaaS product or standing up new infrastructure. This release is mostly a correctness release: it closes three ways an audit log can silently develop holes (changes committed without their audit row, collection history lost on owner deletion, a corrupt file that blocks all later reads) and makes the retention/purge tool refuse to act rather than act on bad data. That is the difference between "we log changes" and "we can defend the log." Cost is contained: an existing database plus a file, no vendor.
To engineering (the short version):
onFlush instead of postFlush — the previous behaviour committed the entity change and lost the audit row. Audit completeness is now enforced pre-transaction wherever the identifier is readable at that point.TypeError on every flush; getOriginalEntityData() returns the referenced column value, which was being handed to isInIdentityMap().onFlush, because Doctrine's Collection::clear() snapshots after emptying and owner deletion bypasses collection scheduling entirely. Both previously produced empty removed lists.FileStorage truncates a partially-written record under the same exclusive lock, so one bad write no longer poisons every subsequent read and purge.PHP_INT_MAX) are now rejected instead of being read as end-of-data.Two things to plan for, not discover:
doctrine/dbal floor is now ^4.2. Audit this against every service before scheduling the bump.date is now ATOM with offset. A --before boundary was previously honoured up to fourteen hours off when the purge ran in a different timezone. Old records still read, in the reader's timezone as before — so a mixed-format file is readable but not uniformly interpretable. If you retain long windows, know which side of the change a given file was written on.Positioning: adopt at v4.1 or later, not earlier. Everything before it is a version whose failure mode was missing audit rows.
How can I help you explore Laravel packages today?