New Release: Doctrine DBAL 3.2.0

Posted on November 26, 2021 by Sergei Morozov

We are happy to announce the immediate availability of Doctrine DBAL 3.2.0. As most of the minor releases, this one focuses on new features, improvements and deprecations of the old APIs. Here are some details on the most significant features and improvements:

Platform-aware schema comparison (#4746)

Up until this release, the logic of comparing database schemas had a major design flaw: it took into account only the abstract schema definitions without taking the target platform into account.

This flaw would lead to multiple issues which shared the same root cause: the two definitions could be considered different by the DBAL, but they would produce the same DDL.

For instance, consider the two column definitions:

// old schema
$column1 = new Column('contents', Type::getType('text'));

// new schema
$column2 = new Column('contents', Type::getType('text'), ['default' => 'Hello, world!']);

If we compared them with the comparator, we'd get a diff:

$comparator = new Comparator();
$comparator->diffColumn($column1, $column2);
// array(1) {
//   [0] =>
//   string(7) "default"
// }

This might be valid for the platforms that support the DEFAULT constraint on TEXT columns but isn't valid for those that don't support it (e.g. MySQL). Regardless of the diff, both definitions would produce the same DDL on MySQL:


An attempt to migrate the old schema to the new one would produce a false-positive diff but applying it wouldn't result in any schema changes.

A false-negative diff was also possible. Consider these following example:

// old schema
$column1 = new Column('settings', Type::getType('json'));

// new schema
$column2 = new Column('settings', Type::getType('json'), ['length' => 16777215]);

Comparison of the above column definitions should have triggered a diff on MySQL and migrate the underlying column from TEXT to MEDIUMTEXT but it didn't, because the DBAL would ignore the length of the TEXT columns.

Apart from that, the DBAL would compare only a subset of the definitions, so some column options as the character set and collation weren't taken into account during comparison at all.

The new approach

Instead of comparing abstract definitions on a per-property basis, the new implementation compares the DDL that is generated from both definitions for the target database platform. If the definitions produce the same DDL, they are considered equal. According to the tests and the number of resolved issues, this approach should be more accurate and less error-prone.

Implementing this approach was impossible without introducing a new API which rendered the existing API obsolete.

Prior to DBAL 3.2.0, the schema comparator could be only instantiated directly via the new keyword:

$comparator = new Comparator();

Instantiated like this, the comparator doesn't have a notion of the target database platform and cannot perform the comparison properly. That is why, this way of instantiation is deprecated in favor of instantiating the comparator by the schema manager:

$schemaManager = $connection->createSchemaManager();
$comparator = $schemaManager->createComparator();

This way, the schema manager can instantiate a platform-specific comparator and provide it with the necessary context (e.g. the default collation used by the database).

While the old API is still available, it is recommended to use the new API for more accurate comparison.

Support for psr/cache (#4620)

Since the Doctrine Cache library is being sunset, the new DBAL release introduced the ability to use a PSR-6 compatible implementation for result caching.

While both the doctrine/cache and psr/cache APIs will be supported until the next major DBAL release, we recommend users to switch to a PSR-6 compatible implementation in their projects.

Support for psr/log (#4967)

The SQLLogger interface was designed long ago and has certain limitations: there is no way to log messages at different logger levels and it is really challenging to extend the logger functionality without introducing breaking API changes.

The new DBAL release introduces a new middleware that can delegate logging to a PSR-3 compatible implementation.

Note that the new logger won't produce the messages identical to the ones produced by the old one. If you have any processes built around analysing log messages, you may need to make some changes before adopting the new API.

Always cache the full result (#5003)

The implementation of the result cache prior to DBAL 3.2.0 would store the result set in the cache only once it was fetched completely. It led to the following issues:

  1. If the result isn't yet cached and its consumer didn't fetch it completely, the query would be executed again.
  2. In case of a cache miss, the DBAL would get() the cache entry twice: once to fetch the data and once to merge the just fetched result with other results that may be stored in the cache.

The new implementation stores the results in the cache right after they were fetched. It simplifies the caching layer significantly and makes its behavior more straightforward.

Add events for Transaction begin/commit/rollback (#4622)

The new DBAL version introduces three more transaction-related events:

  • onTransactionBegin,
  • onTransactionCommit,
  • onTransactionRollBack.

Subscribing to those might be helpful if the application logic integrates the database transaction flow with the business logic implemented outside the database. For instance, in the filesystem.

Basic exception handling in IBM DB2 and SQL Server drivers (#4929, #4928)

The DBAL provides a mechanism that converts driver-specific error codes to portable error-specific exceptions. For instance an attempt to insert NULL into a column that has a NOT NULL constraint applied will result in error with the code 1566 on MySQL and in ORA-01400 on Oracle. The DBAL will convert these two errors to a portable NotNullConstraintViolationException.

Historically, the DBAL drivers based on the ibm_db2, sqlsrv and pdo_sqlsrv extensions did not support this feature and would thow a generic DriverException.

As of DBAL 3.2.0, this feature is supported by all bundled drivers.

Improved AbstractPlatform::getLengthExpression() (#4855)

Although the LENGTH expression was implemented for all supported database platforms, the different implementations didn't have consistent semantics:

  1. Most implementations would return the length in characters (Unicode code points), which is the most expected behavior.
  2. The implementations for MySQL and IBM DB2 would return the number of bytes. It worked fine for the strings that consisted only of the ANSI characters, but an attempt to use it with a wider range of characters would produce an unexpected result. For instance, the length of the string 'Привет, мир!' might be reported as 19 instead of 12.

As of DBAL 3.2.0, all platforms return the length in Unicode points according to the character set used by the database connection. Note, SQL Server supports UTF-8 only as of SQL Server 2019.

You can find more details in the release notes.

DBAL 3 SQL Injection Security Vulnerability fixed (CVE-2021-43608)

Posted on November 11, 2021 by Benjamin Eberlei

We have released a new version Doctrine DBAL 3.1.4 that fixes a critical SQL injection vulnerability in the LIMIT clause generation API provided by the Platform abstraction.

We advise everyone using Doctrine DBAL 3.0.0 up to 3.1.3 to upgrade to 3.1.4 immediately.

The vulnerability can happen when unsanitized input is passed to many APIs in Doctrine DBAL and ORM that ultimately end up calling AbstractPlatform::modifyLimitQuery.

As a workaround you can cast all limit and offset parameters to integers before passing them to Doctrine APIs.

This vulnerability has been assigned CVE-2021-43608.

New Release: Doctrine ORM 2.9 with Attributes, Typed Properties, more

Posted on May 24, 2021 by Benjamin Eberlei

We have released a new minor version 2.9 of Doctrine ORM, the first version with support for using PHP 8 Attributes as a new driver for mapping entities and several other changes. See all changes and contributors in the Changelog on Github.

Attributes Mapping Driver

The following code example shows many of the mappings that are re-using the annotation classes for familiarity:

use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping AS ORM;

#[ORM\Entity(repositoryClass: PostRepository::class)]
class Post
    #[ORM\Column(type: Types::INTEGER)]
    #[ORM\Id, ORM\GeneratedValue(strategy: 'AUTO')]
    private ?int $id;

    #[ORM\Column(type: Types::BOOLEAN)]
    private bool $published = false;

    #[ORM\Column(type: Types::SIMPLE_ARRAY)]
    private array $text = [];

    #[ORM\ManyToOne(targetEntity: User::class)]
    public $author;

    #[ORM\ManyToMany(targetEntity: Tag::class)]
    #[ORM\JoinTable(name: "post_tags")]
    #[ORM\JoinColumn(name: "post_id", referencedColumnName: "id")]
    #[ORM\InverseJoinColumn(name: "tag_id", referencedColumnName: "id")]
    public Collection $tags;

Typed Property Defaults

Since PHP 7.4 types can be declared on class properties and Doctrine now uses these type declarations to reduce amount of mapping boilerplate:

  • Columns don't need the type definitions
  • ManyToOne and OneToOne don't need target entity definitions


use Doctrine\ORM\Mapping AS ORM;

#[ORM\Entity(repositoryClass: UserRepository::class)]
class User
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
    public ?int $id = null;

    public \DateTime $created;

    public Email $email;

Psalmified APIs

Improved the documentation to make sure static analysis tools and IDEs know about the right entity classes returned from EntityManager, EntityRepository and other public ORM APIs. This includes generics support when you extend EntityRepository.

use Doctrine\ORM\EntityRepository;
use App\Entity\User;

 * @template-extends EntityRepository<User>
class UserRepository extends EntityRepository


A new query hint is added that allows hydrating entities through DQL that are marked as read only for the unit of work session, as long as they are not yet loaded as writeable:

$dql = 'SELECT u FROM ' . ReadOnlyEntity::class . ' u WHERE = ?1';

$query = $entityManager->createQuery($dql);
$query->setParameter(1, $user->id);
$query->setHint(Query::HINT_READ_ONLY, true);

$user = $query->getSingleResult();

Index/UniqueConstraints using Field Names

Instead of specifying column names for an index or unique-constraint declaration you can now alternatively use field names.

use Doctrine\ORM\Mapping AS ORM;

#[ORM\Index(fields: ["isPublished"])]
class Post
    public bool $isPublished = false;

This simplifies mapping as the column names passed through the naming strategy do not need to be known.

INDEX BY Associations

Previously DQL INDEX BY was not possible for assocations, now you can:

$dql = 'SELECT p, u FROM Post INDEX BY JOIN u WHERE = 3';


Doctrine ORM 2.9 rethinks deprecations and integrates with our new doctrine/deprecations library.

  • Undeprecate merge() and detach() as no replacements are available yet
  • Notify Persist Change Tracking: Use Explicit Change Tracking instead
  • DQL SELECT PARTIAL syntax, use Value Objects with SELECT NEW instead
  • EntityManager::flush() with arguments
  • EntityManager::clear() with arguments (use detach)
  • Named Queries in Mapping (use Repository)
  • cli-config.php for console command configuration, inject EntityManagerProvider instead.
  • Deprecate doctrine/cache for metadata caching, use PSR-6 cache instead

Cache Deprecations and PSR-6

Over the next versions we will deprecate use of doctrine/cache and replace it with PSR-6. If you are still using doctrine/cache code in your own application make sure to force the versions to "^1.10" in composer.json. Details

PHP 7.1 Support

ORM 2.9 reintroduces PHP 7.1 support, because it wasn't technically unsupported anyways. No changes were necessary to the code to allow it again except in the testsuite.

The PHP 7.1 support was re-added to allow a very broad approach to prepare for some of the deprecations that are introduced in ORM 2 and will be removed in version 3.0.

Coding Standard Support

Doctrine ORM 2.9 now supports and fully validates against Doctrine Coding Standard version 9.0+. This greatly improves automatic pull request checks as all new violations in a PR get caught and inlined into the PR as comments.

New Release: Doctrine DBAL 2.13.1 and 3.1.0 with important Forward Compatibility fix

Posted on April 19, 2021 by Benjamin Eberlei

Last month we released DBAL 2.13.0 as an important push for the ecosystem towards DBAL 3 with an extensive deprecation and forward compatibility layer.

We made a few mistakes, given that the forward compatibility layer is quite complex. As such we have now released Doctrine DBAL 2.13.1 and 3.1.0 with two new APIs that improve the forward compatiblity.

The problem lies in Statement::execute(): 2.13.0 would return a bool and 3.0.0 would return a Result from this method. This kind of API change cannot be handled with a forward compatibility.

As such we introduced two new APIs on Statement that replace execute(). When the old code was:

$statement = $connection->prepare('SELECT * FROM tbl WHERE col = ?');

$rows = $statement->fetchAll();

Then the new code is now:

$statement = $connection->prepare('SELECT * FROM tbl WHERE col = ?');
$result = $statement->executeQuery();

$rows = $result->fetchAllAssociative();

The DBAL 2.13 forward compatiblity layer supports both versions of all code and returns a Statement/Result hybrid that has all the APIs that the DBAL Statement had up until version 2.12. This way you can move at your own pace from the old to the new API in your code.

Thank you again to mdumoulin for the work on improving the forward compatiblity and to Sergei Morozov for the thorough reviews and comments.

Again I want to highlight the Runtime Deprecations library that we introduced to support this migration. You can integrate this with your log stack during development and testing:

use Doctrine\Deprecations\Deprecation;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('doctrine');
$log->pushHandler(new StreamHandler('deprecations.log', Logger::INFO));


Or alternatively using PHP's global error handler:


See the 2.13 blog post for more information about the migration to DBAL 3 and strategy recommendations.

New Release: Doctrine DBAL 2.13 with Deprecations and Forward Compatibility

Posted on March 29, 2021 by Benjamin Eberlei

We have released DBAL 2.13, what we plan to be the last minor version in the 2.x family of Doctrine DBAL. This release includes additional forward compatibility to DBAL 3 around Statement and Result API and with an integration in our new deprecations logging library.

In addition this DBAL release re-enables PHP 7.1 and 7.2 compatibility to give as much flexibility as possible to everyone with forward compatibility.

Statement and Result Forward Compatibility

DBAL 3.0 extracts all fetch-methods from the Statement API and moved them to a new Result API that is returned from Statement::execute. We have backported this API to 2.13 - so that you can support writing code for both DBAL 2 and 3 at the same time.

Old code:

$statement = $connection->prepare('SELECT * FROM tbl WHERE col = ?');
$statement->bindParam(1, $value);

while (($row = $statement->fetch()) !== false) {

$connection->executeQuery('SELECT * FROM tbl')->fetchAll();

New Code:

$statement = $connection->prepare('SELECT * FROM tbl WHERE col = ?');
$statement->bindParam(1, $value);
$result = $statement->executeQuery();

while (($row = $result->fetchAssociative()) !== false) {

$connection->executeStatement('SELECT * FROM tbl')->fetchAllAssociative();

The Result Fetching API was improved to use more human-readable names:

// Old

// New
$result = $stmt->execute();

Many more changes have been made on the public API and also for the internals, but these are the most common ones.

Thank you to mdumoulin for the work on improving the forward compatiblity.

Deprecations Logging

We have wrestled internally for a long time with the strategy on runtime deprecation going forward and settled on introducing a small, new API for reporting the usage of deprecated APIs.

The reason for this abstraction is the potential for side effects caused by an error handler and the potential overhead. We expect our deprecations to be triggered a few hundred times in some requests as such the production overhead must be minimal.

This means deprecation logging is disabled by default and you must enable it to either use @trigger_error or a PSR-3 compatible logger.

See the deprecation library for details on how to configure and use it.

PHP 7.1 and 7.2 Support

A few large Doctrine DBAL deployments still support older versions of PHP that are not officially supported anymore, but are covered by support of a few Linux distributions.

To provide the largest possible flexibility to the ecosystem to run code with both DBAL 2 or 3 this version of Doctrine DBAL will work again with PHP 7.1 and 7.2

Migrate to DBAL 3

We recommend a three step strategy to move your code-base and that of your dependents to DBAL 3. It depends if you are working on a library or platform that is dependent upon, or if you are working on a standalone application.

For a standalone application:

  1. Upgrade to DBAL 2.13 and enforce "^2.13" as a version constraint in composer.json
  2. Enable deprecation tracking and eliminate all deprecations triggered in your codebase.
  3. After fixing all deprecations, update composer constraint to "^3.0". Doctrine will upgrade to version 3 if all other dependencies you are using are ready as well to upgrade to version 3. If it fails, you need to identify and update the dependencies as well.

For a library, framework or platform:

  1. Upgrade to DBAL 2.13 and enforce "^2.13" as a version constraint in composer.json
  2. Enable deprecation tracking and eliminate all deprecations triggered in your codebase. Release a version so that all plugins and downstream users can be notified of using deprecated Doctrine DBAL directly themselves.
  3. After fixing all deprecations, update composer constraint to "^2.13 | ^3.0". Doctrine will only upgrade to version 3 if all other dependencies you are using are ready as well to upgrade to version 3.

We recommend the following strategies to detect the use of deprecated code:

  • Use Psalm, other static analyzers or IDEs to detect the use of deprecated code.
  • If you have an extensive test-suite, register a PSR-3 logger with Doctrine Deprecations to catch all deprecations while running the tests.
  • Otherwise register a PSR-3 logger with Doctrine Deprecations in development or staging only and collect and fix them as well you can. This could be done for a longer amount of time of days, weeks or months.
  • If that is not possible, register a PSR-3 logger in production. Make sure to eliminate high frequency deprecations quickly or call ignoreDeprecation to snooze them to avoid overhead.

New Major Release: Doctrine DBAL 3.0

Posted on November 17, 2020 by Benjamin Eberlei

We have released a new major version of Doctrine DBAL, version 3.0.0. This new major version comes almost 10 years after DBAL 2.0 was released on December 2010, then coupled into the ORM 2.0.

Today Doctrine DBAL is released independent of the ORM, thanks to Composer and sees its new major version before the ORM.

This release was made possible foremost by Sergei Morozov, our primary DBAL maintainer, who has spent countless hours working on the package since 2016. Thank you!

See the Release Notes for a detailed list of changes.

This blog post covers a few of the major changes in a bit more detail to give you an idea of what DBAL 3.0 looks like.

Decouple DBAL from PDO

The major theme of DBAL 3.0 is the decoupling from PDO. Instead of copying the API verbatim like DBAL 2.0 did, DBAL 3.0 grows it into a better, more usable direction.

We extract all fetch-methods from the Statement class and moved them to a new Result class that is returned from Statement::execute.

Old code:

$statement = $connection->prepare('SELECT * FROM tbl WHERE col = ?');
$statement->bindParam(1, $value);

while ($row = $statement->fetch()) {

New Code:

$statement = $connection->prepare('SELECT * FROM tbl WHERE col = ?');
$statement->bindParam(1, $value);
$result = $statement->execute();

while ($row = $result->fetchAssociative()) {

The Result Fetching API was improved to use more human-readable names:

// Old

// New

Many more changes have been made on the public API and also for the internals, but these are the most visible ones.

Upgrading to DBAL 3 from 2

DBAL 3 is a real new major release with significant changes to the public API. Depending on your codebase a migration could require non-trivial work. However we do not intend to leave you hanging with DBAL 2 and a future migration:

  1. We intend to support DBAL 2.12 a while longer, including support for the upcoming PHP 8.0, so that there is no rush for you to upgrade to DBAL 3.

  2. DBAL 2.12 already includes forwards compatible API changes for all the new APIs, so that you can migrate your code step by step to the new APIs already.

  3. Deprecated methods in DBAL 2.12 are tagged with the @deprecated doc-block and static analysis tools such as Psalm, PHPStan and Phan can already help you detect using or calling this deprecated code in your application.

  4. We intend to release another version of DBAL 2 which includes optional triggering of deprecation messages at runtime similar to how Symfony deals with deprecations.

As you can see, with these approaches it will be possible for you to smoothly migrate your application from DBAL 2 to 3.

As a note to libraries and frameworks that need to support multiple versions of Doctrine DBAL: We recommend you start out with DBAL 2.12 and migrate all usages of deprecated APIs to their newer counterparts. Then once you have managed this, you can allow 3.0 and try to get your code working with both versions. Unfortunately this may not be possible for all cases, because we could not provide replacement APIs for everything and some features have been dropped between DBAL 2 and 3.


DBAL 3 is a huge first step towards a modern database abstraction layer, independent from the legacy of PHP and PDO API design. In the future we plan to improve DBAL in other ways that we haven't gotten around yet, such as more API modernization, increased safety with use of strict scalar types in the code base, better error handling and more.

Released doctrine/migrations 3.0-alpha

Posted on April 10, 2020 by Asmir Mustafic

doctrine/migrations 3.0-alpha has been published on the 29th March 2020.

The upcoming 3.0 new major release is the result of almost 6 months of work and brings a completely refactored/rewritten internal structure and some interesting new features.

Why a new major release?

The doctrine/migrations v1.x codebase is 10 years old, and in the past years a lot of features have been added on top of its initial architecture.
doctrine/migrations 2.0 was released a bit more than a year ago. This major release did a bit of cleanup, but the general structure remained the same. In this schema you can see the dependencies between classes in the latest 2.3.x branch:

The red lines are circular dependencies (and we already know that in software development circular dependencies are not a good thing).

In doctrine/migrations 3.x, most of the internal classes have been re-written and dependency injection has been widely adopted.
In this schema you can see the dependencies between classes in the latest master branch (release v3.0):

As you can see the circular dependencies are gone. This has been possible thanks to extensive use of dependency injection and applying SOLID principles. To reduce future backward incompatibilities, many classes have been marked as final or as @internal while keeping the functionalities intact. Extensibility is still possible by using dependency injection and providing classes implementing dedicated interfaces.

These schemas have been generated using PhpDependencyAnalysis with this configuration.

New features and improvements

Beside the code quality improvements, there is a a long list of improvements (see below), but the main user-facing feature is the ability to collect migrations from multiple folders/namespaces and to specify dependencies between migrations.

Here a (probably not complete) list of improvements implemented in the upcoming 3.0 release:

  • ability to collect migrations from multiple folders/namespaces and to specify dependencies between migrations
  • doctrine/migrations will write to your database only when running migrations (previously the metadata table was created on the very first command run even if it was a read-only command)
  • Output verbosity can be controlled using the -v, -vv or -vvv command parameters
  • Use of dependency injection allows you to decorate/replace most services
  • Removed usage of console helpers to provide the connection or entity manager in favor of dependency injection
  • Introduced migrations:list command to list the available/executed migrations
  • Introduced migrations:sync-metadata-storage command to explicitly update the metadata schema in case a newer version introduces changes to the metadata table
  • Multiple migrations can be passed to the migrations:execute command
  • More organized output of the migrations:status command
  • Configurations and Dependency Factory are read-only during the migration process
  • The down() migration is optional now
  • Multi-namespace migrations
  • Custom migrations metadata storage
  • Added warning when using the migrations:diff if there are not executed migrations

Backward compatibility

In doctrine/migrations 3.0 a lot of things changed, but for end-users most of the things will look the same. Your migration files do not need any update.

You will have to change your configuration files, as the configuration format has changed. The official documentation contains more information about these changes. This documentation should be particularly helpful if you did also some custom integration with third party frameworks or libraries.

If you wrote custom event listeners, please take a look at them as the method signatures for event listeners have been updated.

Symfony Integration

If you are using DoctrineMigrationsBundle then things are even easier: the 2.3.0 release introduced some deprecation notices and if you have already solved them your configuration is already compatible. If you want you can have a look to the latest configuration format available on the official documentation. You can look more in detail to which changes are needed in the upgrading document.

What is next

In the upcoming weeks, we will be preparing the first beta release and starting the process to reach a stable release. To be able to deliver a good stable release it is important that you test the pre-release and share your feedback!

To try the alpha version, you can run:

composer require 'doctrine/migrations:^[email protected]'

If you are using Symfony:

composer require 'doctrine/doctrine-migrations-bundle:^[email protected]' 'doctrine/migrations:^[email protected]'

You can be also more brave trying the development versions by specifying @dev instead of @alpha when requiring the composer dependencies above.

You can also have a look at the release notes and the upgrading document.

Similarly you can also have a look at the release notes and the upgrading document for the Symfony bundle.

In the alpha release, breaking changes are still possible. In the beta, release breaking changes are possible but will happen only if we will find very unexpected behaviors. When the alpha and beta phase will be completed, a stable version will be made available.


This post was initially published on

Doctrine MongoDB ODM 1.3.0 and 2.0.0-RC2 released

Posted on September 30, 2019 by Andreas Braun

The Doctrine team is proud to announce that MongoDB ODM 1.3.0 and 2.0.0-RC2 have been released. These releases are the culmination of a long effort to migrate the ODM away from the legacy mongo extension to the new MongoDB driver (mongodb extension and PHP library). This results in a number of BC breaks for users, but will enable us to add many new features in future releases, among them support for multi-document transactions.

MongoDB ODM 1.3.0 is a compatibility release targeted for users of the legacy extension that want to migrate to MongoDB ODM 2.0. It helps identify BC breaks by throwing deprecation notices and offering a forward compatibility layer where possible. To efficiently find usages of deprecated code, you can use the PHPUnit bridge developed by Symfony (symfony/phpunit-bridge) which logs all deprecation notices encountered during a run of PHPUnit. You can read more about this component in the Symfony documentation.

MongoDB ODM 2.0.0RC-2 is the recommended package to use for those starting new projects with MongoDB ODM. It ensures that you use the modern API for ODM without having to worry about deprecations. While this is still a release candidate, it is planned to make this version the next stable MongoDB ODM release.

What’s new in MongoDB ODM 2.0?

Most importantly, this version no longer uses the legacy mongo extension. That extension is no longer maintained and does not support server versions beyond MongoDB 3.0. The new MongoDB driver ensures that MongoDB ODM can leverage features and improvements contained in newer MongoDB versions, such as support for multi-document transactions, retryable reads, retryable writes, change streams, and much more.

Changing the driver also means significant changes to some APIs. Most importantly, the GridFS API has been rewritten from scratch to conform with MongoDB’s GridFS spec for drivers. If you’ve used GridFS before, this will be a big change for you, but the new API is much simpler and cleaner to use. Check out the GridFS documentation to find out how to use the new API. Unfortunately, we cannot provide a forward compatibility layer for this, as re-implementing this API atop the legacy driver is not feasible.

Lazy reference support has been changed completely and no longer uses proxy objects from the deprecated doctrine/common library. Instead, it builds on ocramius/proxy-manager, which gives us access to more advanced features like partial proxy loading, which we will start leveraging in future releases.

In 2.0 we dropped support for the YAML mapping of documents. This step was necessary to both reduce the complexity of the code base and lower the burden of maintaining multiple mapping drivers. If you are currently using YAML mappings, we provide a console command to migrate YAML mappings to the XML format. We are currently working on an alternative that allows for a more flexible mapping configuration system, but this is not ready yet and will only be provided in a future 2.x release.

Migrating to MongoDB ODM 2.0

If you are using MongoDB ODM 1.x, the upgrade consists of multiple steps. First, ensure that you are fulfilling the necessary requisites for MongoDB ODM 2.0:

  • PHP version 7.2 or newer
  • ext-mongodb 1.5.0 or newer
  • mongodb/mongodb library 1.4.0 or newer
  • MongoDB 3.0 or newer

If you are already running PHP 7, you will most likely already be running ext-mongodb as the legacy extension is not available for PHP 7. If you are still running PHP 5.x, it is recommended that you migrate to PHP 7 before attempting to use a newer ODM version. You can do so by following the instructions on running ODM 1.x on PHP 7.

Once you fulfill all dependencies, the first step is updating to the latest 1.3 release of MongoDB ODM. If you are using Symfony, you also need to upgrade the ODM bundle to its latest 3.6 version. Once this is done, you can start fixing any deprecation notices that you find. This should be a familiar process for any existing Symfony users. We tried to provide compatibility layers where possible; unfortunately, we could not do so in all cases.

The next step is upgrading to ODM 2.0 directly. For many users, this step shouldn’t be a problem thanks to the compatibility layer in 1.x. There may be some necessary changes depending on the features you use (e.g. GridFS).

What’s next for MongoDB ODM

During the past few years, we focussed our limited development time almost exclusively on the driver migration, which came at the expense of supporting new features in MongoDB. We plan to add support for many of those features in future releases. You can get an overview of what’s planned by checking the roadmap. If you are looking for a specific feature, please let us know in the issue tracker.

While not exhaustive or guaranteed, these are some of the features we plan to implement in future releases:

  • Support for multi-document transactions (on-demand and implicit while flushing the Document Manager)
  • Support for new aggregation pipeline stages and operators
  • Support for the $expr query operator
  • Support for aggregation pipelines in update operations
  • Support for reading documents from views instead of collections
  • Atomic updates for collections using new array update operators

Support timeline

With these releases, we’re also introducing our new support timeline. Along with the two releases announced above, we are also releasing the end-of-life release for MongoDB ODM 1.2. We will not support MongoDB ODM 1.2 any more and encourage users to upgrade to 1.3. Since 1.3 has no additional requirements over 1.2, upgrading should be possible for all users of ODM 1.2.

MongoDB ODM 1.3 will be supported for at least 6 months after the first stable release of ODM 2.0. We will communicate this date when releasing ODM 2.0. After those 6 months, we will either drop support for ODM 1.3 or extend it for another 3 months, depending on the adoption rate of ODM 2.0. We are aware that the number and kind of BC breaks for 2.0 pose a significant challenge for many users, which is why we don’t want to force people to rush into this update.

During the support phase for MongoDB ODM 1.3, we will also continue to provide bug fixes to the MongoDB Abstraction Layer that is used by MongoDB ODM 1.x. This project will reach end-of-life at the same time as MongoDB ODM 1.3, and will no longer be supported beyond that. We encourage users that depend on this library to switch to using the MongoDB PHP Library, which is part of the official MongoDB driver for PHP.

Contributing to MongoDB ODM

We are currently looking for contributors. This doesn’t necessarily mean implementing new features or merging pull requests. Reporting or triaging issues, requesting features, and reporting bugs are all extremely important and helps us deliver better software!

Getting help

The documentation can be found on the website: To get support, contact us via the #mongodb-odm channel within the Doctrine Slack. If you believe you have found a bug, please file a bug report on GitHub.

Doctrine Webinars

Posted on May 30, 2019 by Jonathan H. Wage

As mentioned in the Monetizing Open Source blog post, Doctrine will be regularly organizing online webinars hosted with Zoom. You can join from anywhere in the world with a laptop and an internet connection. We will have topics presented by Doctrine core team members and members of the community.

To get things started we have a few webinars scheduled for the next few months:

Don't see something that you are interested in? Suggest an event topic you would like to see and we will see what we can do. We will be publishing new events in the coming weeks so check back soon!

Monetizing Open Source

Posted on May 21, 2019 by Jonathan H. Wage

In our quest to make Doctrine financially sustainable, we have created Doctrine Company, LLC under which the team can conduct business. We've had a strong 10 years of open source success but we believe that in order for Doctrine to be truly sustainable and to last another decade, we need to diversify and monetize the project. It is our goal to be able to generate enough money through the project to fund full or part time work on the project. Below you will find details of some of our monetization efforts.


Patreon is a platform that allows open source maintainers, artists, creators, etc. to create relationships with their users and offer them benefits for becoming a patron.

If you would like to make a donation to the project, Patreon is the place to do it. Depending on the tier, we offer a few different benefits:

  • A mention on Twitter.
  • Your name and website link on the Doctrine website.
  • Priority responses to Stack Overflow or GitHub issues/PRs.
  • Placement on a Partners page on the Doctrine website, with your logo, link, and a paragraph advertising your company's services.

Become a Patreon of Doctrine today!


Under the Doctrine Company, we are providing consulting and training services to companies that use PHP. The services we offer are not limited to Doctrine itself. Our team specializes in producing high quality PHP. Whether you are starting a new project or modernizing a legacy application, we can help your team level up their skills with tools like the following:

  • Doctrine DBAL - Connect to your favorite RDBMS using Doctrine's database abstraction library.
  • Doctrine Database Migrations - Safely manage your database schema and keep it up to date.
  • Doctrine ORM - Represent your domain model cleanly with plain old PHP objects and ensure the integrity of your data.
  • PHP_CodeSniffer - Keep aesthetic debates out of your code reviews by adopting a coding standard and enforcing it in your build process. We can help integrate Doctrine's own coding standard into your project or help codify your own.
  • Psalm / PHPStan - Statically analyze your codebase and find bugs that would otherwise only be found at runtime in production.

If you are interested, take a look at our Consulting page or contact us at [email protected] for more information.


We will host regular monthly webinars using Zoom. Each month we will have different topics presented to you by members of the Doctrine Core team or greater PHP community. We already have some great topics lined up for the next few months:


Tidelift is a managed open source subscription service backed by creators and maintainers. Development teams get better maintained open source. Maintainers get paid.

We have partnered with Tidelift as a maintainer to guarantee a high level of maintenance for their customers. In return, Tidelift pays Doctrine maintainers a percentage of what the customer pays. Tidelift is attempting to create a marketplace of open source maintainers and customers with the goal of providing higher levels of confidence for commercial entities when using open source. This can sometimes be one of the biggest challenges for using open source in the corporate world. Tidelift is taking a unique approach to solving this problem and we are excited to be a part of it!

Carbon Ads

One of the most valuable assets we have besides software is our website and the traffic we receive every month. You may have noticed some subtle ad placements on our website. These text-based ads are provided by Carbon Ads which is an ad network optimized for reaching designers and developers. We understand ads can be annoying and we hope that our users understand the trade-off we've made by choosing to place ads on our website.


Finally, we are partnering with commercial entities and other projects that use Doctrine to cross promote each other. Through our partner network we hope to introduce our users to vetted services and offerings from which they can benefit. Thanks to our Partners for supporting Doctrine.

View Blog Archive