zitec/doctrine-behaviors
A Doctrine ORM extension that adds reusable entity behaviors such as timestampable, blameable, soft-deletable, sluggable, and sortable through traits and event subscribers, reducing boilerplate in PHP applications.
Architecture fit. zitec/doctrine-behaviors is a set of Doctrine ORM traits plus event subscribers/listeners that add cross-cutting persistence behavior: Blameable, Loggable, Sluggable, SoftDeletable, Uuidable, Timestampable, Translatable, and Tree. Architecturally it is a Symfony/Doctrine-idiom package, not a Laravel/Eloquent one. It slots in only if the application's persistence layer is Doctrine via laravel-doctrine/orm (or a fully Doctrine-backed service). For a conventional Eloquent application, this package is not "integrating" — it is replacing the ORM in the affected domain.
The trait/listener model is sound and well-understood: behaviors are attached declaratively per entity and executed inside Doctrine's UnitOfWork on prePersist/preUpdate/onFlush. That gives consistent, centralized behavior with no per-model boilerplate — the main reason to prefer it over hand-rolled Eloquent traits. Translatable follows the object-translation pattern (a Translation entity per translatable entity, locale-keyed collection, proxy accessors), which is a genuinely better model for multi-locale content than JSON columns, at the cost of joins and more tables.
Integration feasibility. Feasible but non-trivial. Laravel's laravel-doctrine/orm exposes the EntityManager, and the package's subscribers can be attached to Doctrine's EventManager from a service provider. Two wiring points require custom code, and both are the usual source of bugs:
App::getLocale() and must be request-safe in queues, console, and Octane workers (a stale singleton locale is a classic Octane failure).Auth::id() is null.Uuidable also conflicts with Laravel's auto-increment/HasUuids conventions and needs a Doctrine ID generator strategy, and coexists awkwardly with existing integer foreign keys mid-migration.
Technical risk. The dominant risk is adoption, not code quality: 0 stars, 0 dependents, and a version string that still says "Doctrine2" while the ecosystem has moved to ORM 3 (annotations removed, API changes). This reads as a vendor fork published for internal reuse rather than a community-supported library. Secondary risks: the SoftDeletable SQL filter (opt-in per EntityManager) silently leaks deleted rows if disabled or if a native query bypasses it; unique constraints on slugs collide with soft-deleted rows; Timestampable/Blameable listeners do not fire on DQL bulk UPDATE/DELETE, a well-known and frequently missed failure mode.
Key questions.
Stack fit. Only justified under one of two conditions: (a) the application already uses laravel-doctrine/orm and needs these behaviors; or (b) a discrete, read/write-heavy content or catalog module genuinely benefits from Translatable + Tree and the team is willing to own Doctrine there. If the stack is Eloquent-first, the equivalent native path is cheaper and better supported:
| Behavior | Eloquent-native alternative |
|---|---|
| Sluggable | spatie/laravel-sluggable |
| SoftDeletable | built-in SoftDeletes + withTrashed() |
| Timestampable | built-in timestamps |
| Blameable | owen-it/laravel-auditing or observer |
| Loggable | owen-it/laravel-auditing |
| Translatable | spatie/laravel-translatable (JSON) or per-locale tables |
| Tree | kalnoy/nestedset |
| Uuidable | built-in HasUuids |
The strategic read: this package's value is cohesion — one consistent behavior layer — which Eloquent only matches by assembling 5–6 third-party packages with divergent conventions. That is a real argument, but it is an argument for Doctrine, not for this specific fork.
Migration path. Do not attempt a gradual per-model Eloquent→Doctrine migration in the same bounded context. Doctrine's UnitOfWork and Eloquent's query builder do not share an identity map or transaction semantics; a single request writing through both is a correctness hazard (stale entities, double-writes, inconsistent rollback). If migrating, migrate one bounded context end-to-end behind a repository interface, keep the two contexts in separate transactions, and use domain events rather than shared writes.
Compatibility. Verify against a pinned matrix before committing: PHP version, doctrine/orm major, laravel-doctrine/orm version, Laravel major, and database driver. Nested-set Tree and the SoftDeletable filter behave differently across DB platforms (MySQL vs PostgreSQL vs SQLite in tests). Translatable's proxy/__call magic is also hostile to static analysis — budget for PHPStan baseline work.
Sequencing.
Auth-backed blameable resolver, locale resolver, and a soft-delete-aware base repository.Maintenance. Effectively a single-vendor, low-signal dependency — 0 dependents means no crowd-sourced bug discovery, few Stack Overflow answers, and no ecosystem pressure to keep it current. Treat it as first-party code: fork it, own the test suite, and expect to patch ORM-version breakage yourself. MIT license makes that legally clean; it does not make it free. Budget roughly 1–2 engineer-days per quarter for upkeep and upgrade triage.
Support. No commercial support, no visible security policy, unknown test coverage. For a TPM this is a governance item: add it to the dependency register, pin exact versions, and require a documented fallback (drop the behavior traits and hand-roll the listener) for each behavior you depend on.
Scaling.
JOIN FETCH/addSelect on translation collections and repository-level eager-load defaults. This is solvable but must be designed in, not retrofitted.Failure modes to instrument.
UPDATE/DELETE skipping Timestampable/Blameable/Loggable → audit trail silently incomplete.Ramp-up. Doctrine fluency is the real cost. Engineers must understand the identity map, UnitOfWork, DQL, managed-vs-detached entities, and lazy-loading-after-detach before they can safely use these traits — none of which transfer from Eloquent habits. Expect 2–4 weeks to productive competence for a mid-level team, plus the wiring glue above. The behaviors themselves are learnable in hours; it is the surrounding ORM model that costs the month.
Verdict for a TPM. Score 5.97 with opportunity 4.38 reflects the tension accurately: the package is technically competent and the behavior set is genuinely useful, but adoption signal is near zero and the Laravel fit is conditional. Recommend only if Doctrine is already in the stack or a bounded context justifies it; otherwise do not adopt — this fork's cohesion benefit does not outweigh owning a zero-dependency library through an ORM 3 transition.
How can I help you explore Laravel packages today?