 [ ← blog / drupal ](/) Oct 18, 2023  ·  \#drupal  ·  3 min read 

# Writing backward-compatible deprecation fixes for contributed modules will be much easier for Drupal 11



One of the major problems observed in getting contributed modules Drupal 10 compatible was maintaining support for Drupal 9.5, which remains in security support (or remained if it is now past November 1, 2023.) Contributed modules should be compatible with all security-supported versions of Drupal core or more if they so choose. This can be difficult as Drupal 9.5 contained deprecated code removed in Drupal 10. It was up to maintainers and contributors to find workarounds and copy-pasting tricks using `if`/`else` statements with `version_compare`.

If you're interested in these challenges, I recommend catching my talk from MidCamp this year – [Lessons learned from helping port the top contrib projects to Drupal 10](https://mglaman.dev/blog/lessons-learned-helping-port-top-contrib-projects-drupal-10).

## Making backward-compatible calls possible

Luckily, [Drupal 10.1.3](https://www.drupal.org/project/drupal/releases/10.1.3) released a new utility class that will make supporting multiple versions of Drupal core easier while addressing deprecated code. The new class [`\Drupal\Component\Utility\DeprecationHelper`](https://git.drupalcode.org/project/drupal/-/blob/905415d9c46d961211ad3eef2c5ee4dc71876ca4/core/lib/Drupal/Component/Utility/DeprecationHelper.php) and its `backwardsCompatibleCall` method allow code to be executed conditionally based on the current Drupal core version ([change record](https://www.drupal.org/node/3379306).)

For instance, the `user_roles()` function [has been deprecated in Drupal 10.2.0](https://www.drupal.org/node/3349759). Here's an example of using the deprecated `user_roles` function and its replacement using the `DeprecationHelper::backwardsCompatibleCall` method. *Note – the example uses named arguments for demonstration purposes and is not required*.

```php
$result = DeprecationHelper::backwardsCompatibleCall(
    currentVersion: \Drupal::VERSION,
    deprecatedVersion: '10.2',
    currentCallable: fn() => Role::loadMultiple(),
    deprecatedCallable: fn() => user_roles(),
);
```

Let's break down this code. `DeprecationHelper::backwardsCompatibleCall` has four arguments

- `currentVersion` is the version to be checked, which is the version of Drupal from `\Drupal::VERSION`.
- `deprecatedVersion` is the version that introduced the deprecated code path, which happened in the release of Drupal 10.2.0.
- `currentCallable` is the callable to be invoked for the *new* code path.
- `deprecatedCallable` is the callable to be invoked for the *deprecated* code path

The method uses PHP's version\_compare function to determine if `currentVersion` is greater than or equal to `deprecatedVersion`.

I sincerely appreciate [everyone's discussions and bikeshedding of this code](https://www.drupal.org/node/3371619). There was a lot of back and forth over naming and documentation, which is extremely important for a tool like this. It may only be a few lines of code, but we needed to nail the developer experience.

There is a caveat, however. Modules using `DeprecationHelper` must support a minimum version of 10.1.3 for Drupal core. With the release of Drupal 10.2.0 during [the week of December 11, 2023](https://www.drupal.org/about/core/policies/core-release-cycles/schedule), Drupal 10.0.x will no longer receive security support. That means modules can begin choosing to drop support for `10.0.x` and bump their minimum supported version to `10.1`.

## Making drupal-rector backwards compatible

Earlier this year, I wrote about the need to [add backward compatibility to automated code fixes provided through Rector](https://mglaman.dev/blog/adding-backward-compatibility-rector-rules). [Björn Brala (bbrala)](https://www.drupal.org/u/bbrala) has made this a reality: <https://github.com/palantirnet/drupal-rector/pull/250>!

As the [Project Update Bot](https://www.drupal.org/project/project_analysis) delivers automatic code fixes to projects for Drupal 11 compatibility through Rector, we can use `DeprecationHelper` to ensure breaking changes are not introduced. This is a giant leap forward in innovation for Drupal as the community works to reduce manual upkeep and maintenance of Drupal sites.

 

  ![](/themes/custom/mglaman/images/headshot.webp)Thanks for reading

I write about Drupal, PHP, and the quiet infrastructure behind large sites — caching, config, and testing. New posts land every week or two.

 [Subscribe via RSS →](/rss.xml) [About me →](/about-me) 

 



 

  [← Older

Book Review: Modernizing Drupal 10 Theme Development

 ](/blog/book-review-modernizing-drupal-10-theme-development) [Newer →

Documentation added for supported hooks and APIs in Retrofit for Drupal

 ](/blog/documentation-added-supported-hooks-and-apis-retrofit-drupal)