Doctrine ORM 3.0: What Changes for Your PHP Projects

Doctrine ORM 3.0: What Changes in Practice for Your PHP Projects
Released in February 2024, Doctrine ORM 3.0, whose integration in Symfony is officially documented, is the first major version in more than a decade. Far from a simple version bump, this release deeply restructures the internal architecture of the most widely used persistence library in the PHP ecosystem. For teams that rely on Symfony or on standalone Doctrine, understanding the scope of these changes is essential to plan the migration calmly.
Immediate Changes for Developers
The End of Annotations, Welcome PHP 8 Attributes
The most visible change concerns entity mapping. DocBlock annotations (/** @ORM\Entity */) are no longer supported. Only PHP 8 attributes (#[ORM\Entity]) and XML files remain available. YAML configuration, deprecated since ORM 2.x, is also removed for good.
This choice sets PHP 8.1 as the minimum version and aligns Doctrine with modern language standards. Rector can automate this migration (in French) from annotations to PHP 8 attributes. For projects still using annotations, this migration is the first task to anticipate.
Removal of Deprecated EntityManager Methods
The merge() method disappears from the EntityManager. These methods, a frequent source of subtle bugs tied to the identity map, had been deprecated for several minor versions. Removing them forces the adoption of more explicit patterns for managing the entity lifecycle.
The End of Partial Objects
Partial entity loading is removed. The official recommendation points to DTOs via DQL or the QueryBuilder, a more explicit and more performant approach. This change clarifies the boundary between a managed entity and a read-only projection, an architectural principle that is often overlooked.
A Lighter, Better-Tested Package
The package shrinks from 400 KB to 326 KB, a reduction of nearly 20%. Code coverage rises from 84% to 89%, with notably stronger tests on edge cases. These two indicators reflect a consolidation effort: less legacy code, more reliability.
Technical Deep Dive for Senior Developers
Typed Collections and Static Analysis
Doctrine ORM 3.0 significantly strengthens collection typing. The ArrayCollection and PersistentCollection classes now use PHPDoc generics systematically. A collection property is declared with the type Collection<int, Comment>, which guarantees at the static level that only Comment objects enter the relation.
This changes how errors are detected. Where a typing bug in a OneToMany relation only showed up at runtime, PHPStan (in French) and Psalm can now flag it during analysis. For teams that maintain complex domain models with dozens of relations, the reliability gain is substantial.
Strict Association Validation
The handling of ManyToMany, OneToMany and ManyToOne associations benefits from stricter validation at mapping time. The mappedBy and inversedBy attributes are systematically checked on bidirectional relations. In case of an inconsistency, Doctrine throws an explicit exception instead of silently behaving incorrectly.
This rigor eliminates an entire category of bugs that showed up as unpersisted data or unexpected SQL queries, problems that are particularly hard to diagnose in production.
Evolution of the Proxy System
The proxy mechanism, essential to lazy loading, now relies on lazy ghost objects (via symfony/var-exporter). This new mechanism replaces the old system based on class inheritance and reduces the configuration surface while improving memory management when loading entities.
Lazy ghost objects make proxy pre-generation obsolete. The orm:generate-proxies command was removed in ORM 3.0, because the new mechanism no longer needs proxy files generated in advance.
Identifier Generation Strategies
With DBAL 4, the SEQUENCE strategy is dropped in favor of IDENTITY (based on GENERATED BY DEFAULT AS IDENTITY), which becomes the standard for PostgreSQL in Symfony projects (in French). The AUTO strategy automatically selects the best approach for the database engine. UUIDs and ULIDs are better supported as primary identifiers (in French), which makes distributed architectures easier, since sequential identifiers cause collision problems there. If your project still uses INT columns and is approaching their limits, the article on migrating INT IDs to BIGINT (in French) details the procedure with no downtime.
Embeddables: Richer Modeling
Embeddable objects now natively handle nullable values and nesting. This improvement lets you model composite business concepts, such as a postal address, geographic coordinates or a time slot, without workarounds. The interface was redesigned to make it more intuitive and consistent with the rest of the API.
Need support on your project?
Let's talkArchitectural Vision: DBAL 4, Performance and Migration Strategy
The Implications of DBAL 4
Doctrine ORM 3.0 is compatible with DBAL 3.6 and DBAL 4, but DBAL 4 is actually the deepest change in this transition. DBAL 4 drops support for several legacy drivers, streamlines the connection API and changes how data types are handled. Schema abstractions are simplified, which directly affects migrations and schema generation tools.
For architects, this means that the migration to ORM 3.0 and the one to DBAL 4 must be planned together, even if they can be sequenced. Custom abstraction layers built on top of DBAL will need to be audited. The adoption of PSR-6 for caching, replacing doctrine/cache, is part of this dependency streamlining and improves interoperability with the whole PHP ecosystem.
Impact on Performance
The 20% reduction in package size is not trivial in a large-scale deployment context. Fewer files to load means faster autoloading and a smaller OPcache footprint. The removal of partial objects and the simplification of the event system, with the removal of events such as onClear, shorten the internal execution paths. On high-traffic applications that handle complex entity graphs, these optimizations translate into a measurable drop in per-request latency.
The new proxy system also contributes to this improvement. Lazy ghost objects work without proxy files generated on disk, which removes the associated I/O and simplifies deployment to production.
When to Migrate and How to Sequence the Transition
The migration to ORM 3.0 should not be rushed. The recommended approach follows a rigorous incremental progression:
- Upgrade to Doctrine ORM 2.18 and DBAL 3.x, which expose all the deprecations to handle
- Enable strict deprecation mode and resolve every warning, starting with the migration from annotations to PHP 8 attributes
- Update DBAL to version 4.x, auditing custom abstraction layers
- Move to ORM 3.0 once all deprecations are resolved
- Run the full test suite and validate behavior in a staging environment
For strategic projects, it makes sense to wait until the third-party bundle ecosystem has completed its own migration. Bundles that depend on Doctrine internal APIs, such as event listeners and DBAL type extensions, are the most likely to need updates.
Well-maintained projects that have handled deprecations over the course of minor versions will find this transition relatively smooth. For the others, a structured migration guide (in French) helps sequence the work and control the risks.
The Current State of ORM 3.x
Since the 3.0 release, the 3.x branch has kept evolving with regular minor versions. The latest published version, 3.7, keeps the same requirements: PHP 8.1 minimum and DBAL 3.8 or 4. Migrating to ORM 3 today therefore remains an achievable project without changing your PHP version, and following the releases published on GitHub lets you pick the latest stable release.
Conclusion
Doctrine ORM 3.0 marks a turning point in the maturity of the PHP persistence ecosystem. By removing legacy code, strengthening typing and aligning with PSR standards, this version lays the foundations of a more robust, more performant and more maintainable library. Combined with DBAL 4, it calls for a global architectural review of the persistence layer. The migration demands rigor, but the result is a modernized technical foundation, ready to support the demands of PHP applications for years to come.
Call on our teams to support you in this migration. Our custom web development (in French) service includes support for Doctrine version upgrades.
Going Further
- Rector to modernize your Symfony code, automate the migration from annotations to PHP 8 attributes
- Doctrine ORM Documentation, the official documentation for Doctrine ORM 3.0
- GitHub: Doctrine ORM, the official Doctrine ORM repository
- Symfony Doctrine Documentation, Doctrine integration in Symfony
Have a project in mind?
Our team replies within 48 hours to look at your needs and suggest a suitable approach.
Contact usRelated articles

Symfony and PHP End of Life: The Action Plan
Symfony and PHP end-of-life calendar for 2026, real consequences (CVEs, NIS2, GDPR) and three exit strategies depending on how critical your application is.
Read more →
Elasticsearch vs Algolia for a Symfony Project
Elasticsearch and Algolia meet different needs. A hands-on technical comparison to help you pick the right search engine for your Symfony project and team.
Read more →
Sylius vs PrestaShop: Which E-Commerce Platform?
Sylius and PrestaShop are two open source PHP e-commerce platforms. A technical comparison of architecture, flexibility, security and upkeep to help you choose.
Read more →