phpstan-drupal, drupal-check, drupal-rector, upgrade_status — OH MY 🚀

If you haven’t seen or heard, the Drupal 10 readiness effort is heavy underway. Wait. Drupal 10? Yeah. Drupal 8 will be at its end of life in two months, and Drupal 10 is to be released sometime next year. As the maintainer of phpstan-drupal, there is actually a lot of responsibility on my plate. It serves as the glue to power drupal-check and the Upgrade Status module.

But, first… did you know?

Did you know that this tooling is used to scan every single contributed project on It is. Here’s the Jenkins job for Drupal 10 and Drupal 9. You can see a dashboard on Acquia’s developer portal that displays the results, thanks to Gábor Hojtsy: Drupal 10, Drupal 9. When you review these reports, you will see information about Rector. That’s where the drupal-rector project maintained by comes in.

A tool for a specific job

Every so often, I am asked a few questions:

  • Why do I need Upgrade Status if I have drupal-rector?
  • Is drupal-check required, or can I only use PHPStan?
  • Do I need all of these tools? What can I run in my continuous integration builds?

PHPStan & phpstan-drupal

I do not use drupal-check in any of my projects. I install PHPStan directly with the required extensions phpstan-drupal and phpstan-deprecation-rules. Here’s my nifty one-liner Composer command to add all the dependencies:

composer require  --dev phpstan/phpstan \
phpstan/extension-installer \
mglaman/phpstan-drupal \
level: 5
php vendor/bin/phpstan.phar analyze web/modules/custom

drupal-check (a PHPStan wrapper)

When I first wrote phpstan-drupal, the Drupal community still had many folks balking at having to use Composer. The phpstan/extension-installer package didn’t exist, either. The setup wasn’t horrible, but it required a few steps. The project was inspired and born in an email exchange with Dries.

composer require --dev mglaman/drupal-check

The Upgrade Status module

Enter the Upgrade Status module. Initially, Upgrade Status was essentially the same as drupal-check — just as a Drupal module to provide a user interface and some additional information. Under the hood, Upgrade Status runs PHPStan for you to provide deprecated code analysis.

$output = [];
$error_filename = $this->temporaryDirectory . '/phpstan_error_output';
$command = $this->binPath . '/phpstan analyse --memory-limit=-1 --error-format=json -c ' . $this->phpstanNeonPath . ' ' . $project_dir . ' 2> ' . $error_filename;
exec($command, $output);
php vendor/bin/drush upgrade_status:analyze --all --ignore-uninstalled
- image: circleci/php:7.3-cli
- setup-build
- install-composer
- run:
name: phpcs
command: ./bin/phpcs web/modules/custom
- image: circleci/php:7.3-cli
- setup-build
- install-composer
- run:
name: phpstan
command: ./bin/phpstan analyse web/modules/custom --debug
- image: circleci/php:7.3-cli
- setup-build
- install-composer
- run:
name: Install backend
command: ./bin/drush -y site-install --account-pass=admin
- run:
name: upgrade_status
command: ./bin/drush upgrade_status:analyze --all --ignore-uninstalled

Rector / drupal-rector

I am sure you have also noticed the acceleration in which software is developed and released shipped out. PHPUnit has a new major version every year (except 2021, PHPUnit didn’t ship.) The Symfony framework releases minor versions every six months and majors every two years. And Drupal will begin falling more in line with the Symfony release cycle due to security timelines. That is a lot of code that changes fairly quickly. Especially when you’re in an agency and need to balance client budgets, that’s where Rector saves the day and makes automated code changes possible.

composer require --dev palantirnet/drupal-rector
cp vendor/palantirnet/drupal-rector/rector.php .
php vendor/bin/rector process web/modules/custom

What is next with these tools, are we done?

No! We’re not done.

PHP 8 readiness

Did you know PHP 8 is right around the corner? I mean, it’s here. But did you know that Drupal 10 will require it? There is a meta issue opened for PHPStan to provide better detection of backward-incompatible code. That means we can run PHPStan on PHP 7.4 and find deprecated native functions and PHP 8 incompatibilities before running the code on PHP 8.

Drupal 10

I don’t think we will see much more in terms of deprecations for Drupal 9, but there is still time for them to arrive. That means we need to write Rector rules to help automate those fixes. In fact, there is a policy discussion about making Rector rules a requirement for the deprecation process:

Contributions & end-user testing

We need end-users to test and report bugs! There are a lot of use cases where phpstan-drupal isn’t wiring up PHPStan properly to catch deprecations. Or maybe PHPStan isn’t at all (like detecting deprecated native functions.) These Rector rules rewrite code, but we only have so many samples to test on and ensure they’re doing their job properly.


I think it is worth talking about funding. As the rise of Drupal 10 readiness began, I began to feel extremely overwhelmed with managing phpstan-drupal and drupal-check in my free time. I made a plan to put drupal-check and phpstan-drupal on indefinite development hiatus until I could figure out sustainable development funding. That worked itself out a bit faster than I expected. As I said earlier in the blog post, Florida DrupalCamp sponsored my time to get things in shape and ready.

Thanks for reading!

I know this was a looooong blog post. I appreciate that you took the time to read and reach the end! 💖

Open source developer, working with Drupal and building Drupal Commerce.