-
Notifications
You must be signed in to change notification settings - Fork 0
Description
🚀 Migration Plan: Upgrade Roadiz to Doctrine ORM 3.x
Context
Roadiz currently relies on Doctrine ORM 2.x, which has reached end-of-life. Doctrine ORM 3.x introduces significant internal refactoring, removal of deprecated APIs, and ecosystem alignment (DoctrineBundle 3, DBAL 3+, etc.).
This issue tracks the full migration of Roadiz to Doctrine ORM 3.6.x (stable minor target), ensuring:
- Forward compatibility
- Removal of deprecated APIs
- Improved performance and maintainability
- Alignment with the current Symfony/Doctrine ecosystem
🎯 Target Stack
| Package | Target Version |
|---|---|
| doctrine/orm | ^3.6 |
| doctrine/dbal | ^3 |
| doctrine/doctrine-bundle | ^3 |
| doctrine/persistence | latest compatible |
| doctrine/migrations | latest compatible |
🧭 Migration Strategy (Phased Approach)
We will not attempt a big-bang upgrade. Migration will be done in controlled phases.
Phase 1 — Stabilize on Latest ORM 2.x (Pre-Upgrade Cleanup)
Goal
Eliminate all deprecations under ORM 2.21 before moving to 3.x.
Tasks
- Upgrade to
doctrine/orm:^2.21 - Upgrade to
doctrine/dbal:^3 - Enable deprecation reporting in CI
- Fix all deprecations
- Ensure full test suite passes
- Validate schema:
bin/console doctrine:schema:validate
Why?
Doctrine officially recommends upgrading to the latest 2.x and clearing deprecations before jumping to 3.x.
Phase 2 — DoctrineBundle 3 Upgrade
DoctrineBundle 3 removed legacy support (annotations, YAML mapping, legacy config options).
Tasks
- Upgrade to
doctrine/doctrine-bundle:^3 - Update Symfony config to remove deprecated options
- Ensure cache pools are properly configured
- Remove any legacy
Doctrine\ORM\Tools\Setupusage - Verify event listeners and subscribers still register properly
- Ensure compatibility with current Symfony version
Phase 3 — Mapping Migration (Critical)
DoctrineBundle 3 removes support for:
- ❌ Annotations
- ❌ YAML mapping
If Roadiz uses annotations:
@ORM\EntityThey must be converted to PHP Attributes:
#[ORM\Entity]If YAML mappings exist:
They must be converted to:
- PHP Attributes (preferred)
- OR XML mapping
Tasks
- Scan repository for
@ORM\ - Scan for
.orm.ymlfiles - Convert annotations to PHP attributes
- Remove YAML mapping definitions
- Validate metadata mapping with
doctrine:schema:validate - Clear metadata and proxy cache
Phase 4 — Removed APIs & Breaking Changes (ORM 3)
This is the most critical phase.
1️⃣ EntityManager::merge() Removed
Find
->merge(
Required Refactor
Replace merge usage with explicit load + patch pattern:
$entity = $repository->find($id);
$entity->setFoo($dto->foo);
$em->flush();No automatic graph reattachment exists in ORM 3.
2️⃣ Cascade "merge" Removed
Find
cascade={"merge"}
Action
Remove merge from cascade definitions.
Allowed cascade options:
- persist
- remove
- refresh
- detach
3️⃣ Flush Behavior Review
Audit usage of:
$em->flush($entity);
Ensure no reliance on legacy partial flush semantics.
Prefer full flush unless explicitly safe.
4️⃣ Proxy & Lazy Loading Changes
ORM 3 introduces internal improvements and optional Native Lazy Objects.
Tasks
- Verify lazy loading works in Twig templates
- Verify serialization (API responses)
- Test backoffice entity forms
- Benchmark homepage and node listing performance
- Detect potential N+1 regressions
Phase 5 — Query & Hydration Review
Audit advanced ORM usage:
ResultSetMapping- Custom hydrators
iterate()toIterable()- Scalar hydration
- DQL PARTIAL objects
- Custom query hints
Tasks
- Identify custom hydrators
- Run regression tests on heavy queries
- Validate pagination logic
- Validate DQL compatibility
Phase 6 — Migrations & Tooling
- Verify doctrine/migrations compatibility
- Test schema diff generation
- Test database migrations execution
- Validate fixtures loading
- Validate custom Roadiz CLI commands
- Ensure test database setup works correctly
🔎 Repository Audit Commands
Run these before starting Phase 4:
rg -n "->merge\s*\(" .
rg -n "cascade\s*=\s*\{[^}]*merge|cascade:\s*\[[^\]]*merge|cascade:\s*\{[^}]*merge" .
rg -n "@ORM\\\\" .
rg -n "type:\s*yml|\\.orm\\.yml" .
rg -n "Doctrine\\\\Common\\\\Persistence" .
rg -n "Doctrine\\\\ORM\\\\Tools\\\\Setup" .Attach results to this issue for tracking.
🧪 Testing Requirements
Minimum validation checklist before merge:
- All PHPUnit tests pass
- No deprecations remain
- Admin CRUD fully functional
- Node tree manipulation works
- Translations work
- Media handling works
- API responses unchanged
- No N+1 regressions detected
- Performance regression < +5% on critical pages
⚠️ Risk Areas
| Area | Risk Level |
|---|---|
| Entity graphs | High |
| Backoffice forms | High |
| Serialization | Medium |
| Custom DQL | Medium |
| Event subscribers | Medium |
| Performance | Medium |
📦 Delivery Strategy
Recommended workflow:
- Create branch
feature/orm3-migration - Maintain ORM2-compatible branch for hotfixes
- Enable strict CI rules
- Merge only when fully green
- Squash commits per migration phase
✅ Definition of Done
- Roadiz runs fully on Doctrine ORM 3.6+
- No deprecated APIs remain
- No runtime regressions
- Documentation updated
- CI enforces Doctrine 3 compatibility
- All mapping uses PHP Attributes or XML
This issue serves as the canonical migration blueprint.
All related PRs must reference it.