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);
$statement->execute();

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
$stmt->fetch();
$stmt->fetch(PDO::FETCH_ARRAY);
$stmt->fetchColumn();
$stmt->fetchAll();

// New
$result = $stmt->execute();
$result->fetchAssociative();
$result->fetchNumeric();
$result->fetchOne();
$result->fetchAllAssociative();

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 README.md 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.