Changelog
phil/doctrine-behavioursAll notable changes to phil/doctrine-behaviours will be documented in this file.
Updates should follow the Keep a CHANGELOG principles.
0.1.0-alpha - 2026-11-12
Added
Contract\Timestampable,TimestampableEntityandTimestampListener:created_atandupdated_at, in UTC, by the clock.Contract\Blameable,BlameableEntity,BlameListener,Contract\BlameResolverandFixedBlame:created_byandupdated_by, the identifiers of the users.BlameEraser: finds and replaces a user's name in every blamed table, soft-deleted rows included, for access and erasure requests;tables()lists the blamed tables.Contract\SoftDeletable,SoftDeletableEntity,SoftDeleteListenerandSoftDeletedFilter: a removal becomesdeleted_at, hidden from queries; removed once more, deleted for good.Contract\TreeNode,TreeNodeEntity,TreeListener,Tree,BranchandInvalidTree: materialized paths, branches moved with their node, roots, children, descendants, ancestors and the hierarchy.Tree::children()reads one level, by depth.TreeListenerstarts each flush with no move waiting, andTreeListener::reset()forgets the moves waiting for a flush to end.Contract\Deactivatable,DeactivatableEntity,DeactivationListenerandDeactivatedFilter: a record switched off and back on,activeanddeactivated_at, hidden from queries while it is off.OwnerId,Contract\Ownable,OwnableEntity,OwnerListener,Contract\OwnerResolver,FixedOwner,OwnerEraserandException\InvalidOwner: the owner of a record by a stable identifier, an@refused as it is built, found and replaced in every owned table for access and erasure requests;OwnerEraser::tables()lists the owned tables.Contract\Publishable,PublishableEntity,PublicationWorkflowandPublicationListener: a publication state ofsymfony/workflow, with the dates of publication and withdrawal.Contract\Positionable,PositionableEntity,PositionListener,PositionsandException\InvalidScope: an order within an optional group of columns and to-one relations, a record with no position sent to the end of its group, and moves before, after, first and last in one transaction, each locking the row it is placed against or, first and last, its whole group.Contract\Sluggable,SluggableEntity,ScopedSluggableEntity,SlugListenerandException\SlugUnavailable: a slug byphil/slug, made once and numbered to stay unique in its table, or within the scopeslugScope()names, such as a tenant, a locale or a parent.Contract\Translatable,Contract\Translation,TranslationEntity,TranslationListener,Translations,TranslationSetandException\InvalidTranslation: the text of a record in a row per locale, with a unique index on the record and the locale, read along a fallback chain ofphil/locale-dimensions, a list in one query per class, written without copying from another locale; the slug of a translation is unique within its locale.Contract\Versionable,VersionableEntity,VersionListener,Versions,Version\RecordVersion,Contract\VersionRestoreGuard,AllowVersionRestore,RefuseVersionRestore,Exception\UnknownVersion,Exception\VersionRestoreDeniedandException\InvalidVersionedState: frozen versions numbered from one, the next edit forking the next number, and going back to a past version under a right of its own.Contract\DatedIdentifiable,DatedIdentifierEntityandDatedIdentifierListener: a UUID v7 as the primary key.- The documentation in
doc/, indexed by the README; the soft delete documentation says what a cascaded removal does to each kind of child, and that a to-one relation to a soft-deleted row throwsEntityNotFoundExceptionunder the filter. CONTRIBUTING.md,SECURITY.mdandCODE_OF_CONDUCT.md.