StofDoctrineExtensionsBundle
Symfony bundle wiring gedmo/doctrine-extensions behaviors (sluggable, translatable, timestampable, tree) into Doctrine entities
Repository Health
Technical Analysis
StofDoctrineExtensionsBundle is the standard Symfony integration for gedmo/doctrine-extensions, the widely used collection of Doctrine ORM/ODM behavior extensions. It registers Doctrine event listeners for behaviors like Sluggable (auto-generating URL slugs), Translatable (multi-language entity fields), Timestampable (auto-managed created/updated timestamps), Tree/NestedSet (hierarchical data), Loggable (entity audit logs), Sortable, and Uploadable, and exposes each as a Symfony-configurable service rather than requiring manual Doctrine event subscriber wiring.
Applications enable only the extensions they need via bundle configuration (config/packages/stof_doctrine_extensions.yaml), and annotate or attribute their entity classes to opt into a given behavior, letting Doctrine transparently populate slug/timestamp/translation fields on persist and update.
What You Get
- Symfony service definitions and DI compiler passes (src/DependencyInjection) that register only the gedmo extension listeners enabled in bundle config
- Doctrine event listener wiring (src/EventListener) connecting
prePersist/preUpdatelifecycle events to the underlying gedmo extension behaviors - Support for every gedmo behavior: Sluggable, Translatable, Timestampable, Blameable, Tree/NestedSet, Loggable, Sortable, SoftDeleteable, and Uploadable
- An
Uploadablefile-handling integration (src/Uploadable) for entities that manage uploaded files as part of their persistence lifecycle - Configuration-driven enable/disable per extension, so applications only pay for the listeners they actually use
Common Use Cases
- Auto-generating and maintaining URL-friendly slugs from an entity’s title field (Sluggable)
- Tracking created-at/updated-at timestamps on entities without manual lifecycle callbacks (Timestampable)
- Building multi-language content models where translatable fields are stored per-locale (Translatable)
- Modeling hierarchical data such as category trees or nested comments (Tree/NestedSet)
- Maintaining an audit log of entity changes for compliance or debugging (Loggable)
Under The Hood
Architecture — The bundle is a configuration and dependency-injection layer over gedmo/doctrine-extensions, which does the actual behavior implementation as Doctrine event listeners. src/DependencyInjection (including Compiler compiler passes) reads the bundle’s YAML config to decide which of the ~9 available extensions to register as Symfony services, then wires each corresponding gedmo listener into Doctrine’s event manager so it fires on prePersist/preUpdate/postLoad for annotated/attributed entities. src/EventListener bridges Symfony-specific concerns (like resolving the current user for Blameable, or the current locale for Translatable) into the values gedmo’s listeners expect. src/Uploadable adds Symfony-specific file-handling glue for the Uploadable extension. Because each extension is independently toggleable, only the listeners actually enabled in configuration are registered against Doctrine’s event manager, avoiding unnecessary lifecycle overhead for unused behaviors. Tech Stack — PHP 8.1+, depends directly on gedmo/doctrine-extensions (^3.21) plus standard Symfony 6.4-8.0 components (cache, config, dependency-injection, event-dispatcher, http-kernel). Enforces static analysis via PHPStan with strict rules, deprecation rules, and Symfony/PHPUnit-specific PHPStan extensions. Code Quality — A compact codebase (27 PHP files under src/) focused purely on the Symfony-integration seam, since behavior logic itself lives upstream in gedmo/doctrine-extensions; this separation keeps the bundle’s own surface area small and its test/analysis tooling (PHPStan strict + deprecation rules) tight. API Design — Enabling a behavior is typically a one-line config toggle plus an attribute/annotation on the entity property (e.g. #[Gedmo\Slug(fields: ['title'])]), keeping the integration point minimal and declarative rather than requiring manual event-listener registration in application code.