alengo/doctrine-compatibility-bundle

Compatibility fixes for Sulu 3 with Doctrine ORM 3.x and Gedmo DoctrineExtensions

Maintainers

Package info

github.com/alengodev/SuluDoctrineCompatibilityBundle

Type:symfony-bundle

pkg:composer/alengo/doctrine-compatibility-bundle

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.1 2026-04-05 18:32 UTC

This package is auto-updated.

Last update: 2026-04-05 18:46:06 UTC


README

A Symfony bundle that fixes runtime incompatibilities between Sulu 3, Doctrine ORM 3.x, and Gedmo DoctrineExtensions.

The Problem

Sulu 3, Doctrine ORM 3.x, and Gedmo DoctrineExtensions all underwent major version changes around the same time. The combination of these three libraries produces three distinct bugs that surface at runtime.

1. Gedmo TreeListener fails for Sulu's Page entity

Sulu\Page\Domain\Model\Page is declared as a <mapped-superclass> in Sulu's ORM XML. Gedmo's ExtensionMetadataFactory explicitly returns [] for mapped-superclasses, so any call to getConfiguration() or getStrategy() with SuluPage::class throws:

UnexpectedValueException: Tree object class: Sulu\Page\Domain\Model\Page must have tree metadata at this point

2. Gedmo TreeObjectHydrator fails with Doctrine ORM 3.x

Doctrine ORM 3.x removed the mappedBy property from owning-side ManyToOneAssociationMapping. Gedmo's hydrator unconditionally accesses it for all associations, throwing:

Error: Unknown property "mappedBy" on class Doctrine\ORM\Mapping\ManyToOneAssociationMapping

3. Inherited association mappings missing declared property

When extending Sulu's Page or Article entities with Doctrine ORM 3.x and report_fields_where_declared: true, inherited association mappings have null as their declared property, causing schema validation errors.

Installation

composer require alengo/doctrine-compatibility-bundle

The bundle registers itself automatically via Symfony Flex.

Configuration

The default configuration works for standard Sulu projects where the concrete Page entity is App\Entity\Page. To override:

# config/packages/alengo_doctrine_compatibility.yaml
alengo_doctrine_compatibility:
    page_entity_class: App\Entity\Page  # adjust if your class differs

The configured class must extend Sulu\Page\Domain\Model\Page.

How It Works

SuluPageAwareTreeListener

Extends Gedmo's TreeListener and overrides getConfiguration() and getStrategy(). Any call with Sulu\Page\Domain\Model\Page is transparently delegated to the configured concrete Page entity class, which has valid tree metadata.

Registered via CompilerPass — overrides the stof_doctrine_extensions.listener.tree service after all bundle extensions have loaded, ensuring correct behavior regardless of bundle registration order.

SafeTreeObjectHydrator

Extends Gedmo's TreeObjectHydrator and overrides getChildrenField() to skip owning-side ManyToOne associations before accessing mappedBy, which does not exist in Doctrine ORM 3.x for owning-side mappings.

Registered as the sulu_page_tree hydrator via CompilerPass, overriding Sulu's default registration across all configured entity managers.

InheritedAssociationDeclaredFixerSubscriber

Listens to Doctrine's loadClassMetadata event and resolves the declared property for inherited association mappings where it is null, by walking the class hierarchy via reflection.

Requirements

Package Version
PHP ^8.2
Sulu ^3.0
Doctrine ORM ^3.0
Gedmo DoctrineExtensions ^3.0
stof/doctrine-extensions-bundle ^1.11
Symfony ^7.0

License

MIT — alengo.dev