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.
doctrine/dbal to ^4.2; the audit schema depends on Types::ENUM and Column::getValues(), which do not exist in 4.0/4.1..example/: a runnable micro-kernel that audits a product nomenclator into a second database and a JSONL file, with scenarios for every capability. Run .dev/validate/all.sh --example against MySQL/MariaDB before wiring your own app; its CI job shows the intended setup.EntityManager, UnitOfWork, and onFlush/postFlush semantics rather than model events.--before on the JSONL sink to bound retention.Stringable value object — Uuid, Ulid, or a uid mapping — and are recorded in string form. Read history with (string) $id, not the raw object.Collection::clear() now records the join rows in the removed list, so "who unlinked what" history survives.--before. New JSONL records stamp date in ATOM with offset, so a boundary means the same instant regardless of the host running the purge. Pair file-storage purges with whatever pruning you do on the audit tables.FileStorage alongside the database trail for archival or log shipping. Its exclusive-lock writes and truncate-on-failure behaviour keep the JSONL readable for downstream consumers and later purges.--identity for CLI/ops investigations. Quote values that must stay strings: --identity='code="007"'. In application code, cast identifiers to string before lookup..example/ scenarios in your own suite and gate with .dev/validate/all.sh --example; the example covers MySQL and MariaDB, including enum-column stability.onFlush, before the transaction opens, when the identifier is readable there. That is much safer than the old postFlush throw after commit, but it is still a design constraint: use a surrogate ID or an explicit identifier accessor. If the identifier is not readable at onFlush, don't assume a later commit saves you.--identity casts unquoted values. code=007 becomes the integer 7 and matches nothing. Quote numbers, references, and anything keyword-like.PHP_INT_MAX no longer saturate into an empty page. Code that relied on silent empty pages will now see errors; treat that as a correctness signal.<file>.purge kept-set by design; an incomplete one is deleted and the real cause reported. If <file>.purge exists, restore it before rerunning. Update operator runbooks to check for it rather than assuming the main audit file was untouched.--before can be off by up to fourteen hours for the old records; migrate or tighten boundaries.onFlush. Collection and owner removals now query the database while rows still exist. This is the right trade-off for correctness, but benchmark bulk deletes and large clear() operations.FileStorage truncates a record whose write failed after emitting bytes, under the same lock. You should no longer need manual JSONL repair for torn lines — but don't reintroduce corruption by writing to the file outside the storage API.How can I help you explore Laravel packages today?