Upgrading from drupal 8 to drupal 9 needs to be done with composer. This guiding screencast and blog post can guide you.
For a starter, make sure you remove drupal/console first (!). This will prevent you from having a loop in dependencies for the symfony package:
composer remove drupal/console
Look for drupal/core-recommended or drupal/core in composer.json and remove the line(s):
"drupal/core-recommended": "^8.9.0"
Then run composer update again:
composer update
This will remove drupal core from your installation, but update the necessary contrib that is causing a lot of inconsistencies and package constraint sh*it ;).
If you have drush and devel, which are widely used, also manually edit the versions:
"drupal/devel": "^4.0",
"drush/drush": "^10.0.0",
If you nog add this line and update, we are getting there! First, the first version of drupal 9:
"drupal/core-recommended": "9.0.0",
composer update
This resulted for me in the following:
Problem 1
- drupal/core 8.0.0-beta6 requires doctrine/common dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5 -> found doctrine/common[2.1.3, ..., 2.13.x-dev, 3.0.0, ..., 3.2.x-dev] but it does not match the constraint.
- drupal/swiftmailer[1.0.0-beta1, ..., 1.0.0-beta2] require drupal/core ~8.0 -> satisfiable by drupal/core[8.0.0-beta6, ..., 8.9.x-dev].
- You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1,
As it appears, there is an incompatibility with drupal/swiftmailer.
Above we saw that there was an issue with drupal/swiftmailer. I remove this line from composer:
"drupal/swiftmailer": "^1.0@beta",
composer update
After this, I ran into this with drupal/recaptcha. Repeat the step of removing these lines in composer.json.
Finally, we see our drupal 9 arriving.
- Updating twig/twig (v1.42.5 => v2.12.5): Loading from cache
- Updating symfony/yaml (v3.4.41 => v4.4.9): Loading from cache
- Downgrading symfony/polyfill-php80 (v1.20.0 => v1.17.0): Loading from cache
- Updating symfony/var-dumper (v4.4.17 => v5.1.0): Loading from cache
- Installing symfony/translation-contracts (v2.1.2): Loading from cache
- Updating symfony/validator (v3.4.41 => v4.4.9): Loading from cache
- Updating symfony/translation (v3.4.41 => v4.4.9): Loading from cache
- Installing symfony/service-contracts (v2.1.2): Loading from cache
.........
In step 4 we removed some modules that caused issues for my D9 upgrade. Now D9 is finally there, we re-add them:
composer require drupal/swiftmailer drupal/recaptcha
Using version ^2.0 for drupal/swiftmailer
Using version ^3.0 for drupal/recaptcha
For linkit, I had to require a specific version in order for it to work:
composer require drupal/linkit:6.0.0-beta2
We are now on Drupal 9.0.0. Perform your database updates first:
drush updb -y
After this, change your drupal/core-recommended line in composer.json to:
"drupal/core-recommended": "^9.0.0",
And update again (do not forget to perform drush updb again after this):
composer update
[sidenote here: in production, it is not always possible to upgrade to 9.0.0 first. It also works to directly push your working drupal 9 composer.json to production and upgrade from 8.9.x to 9.2 and then run database updates]
There is a 'why'-command to get more info on where the dependencies come from.
composer why symfony/var-dumper
drupal/devel 2.1.0 requires symfony/var-dumper (~2.7|^3|^4)
drush/drush 9.7.2 requires symfony/var-dumper (^3.4 || ^4.0)
psy/psysh v0.10.5 requires symfony/var-dumper (~5.0|~4.0|~3.0|~2.7)
In this case it was clear that devel and drush are the ones that need to get updated. We add them in our update command and run again:
composer update drupal/core-recommended drush/drush drupal/devel --with-dependencies
Lately I've been stumbling on the following composer 2 issue:
Problem 1
- Root composer.json requires composer/installers 1.7 -> satisfiable by composer/installers[v1.7.0].
- composer/installers v1.7.0 requires composer-plugin-api ^1.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
Solution: add this to your composer.json:
"composer/installers": "^1.7",
and run
composer update
We've updated our installation, but this does not mean our custom code is compatible. Luckily there is a simple way for checking. The drupal-check package will inspect your code:
composer require mglaman/drupal-check --dev
Now run
drupal-check -a web/modules/custom
The result was the following:
------ ----------------------------------------------------------------------
Line alter_entity_autocomplete/src/EntityAutocompleteMatcher.php
------ ----------------------------------------------------------------------
28 Cannot call method getReferenceableEntities() on object|false.
35 Call to an undefined static method Drupal::entityManager().
36 Call to an undefined static method Drupal::entityManager().
------ ----------------------------------------------------------------------
Now I need to check the lines of this custom module and fix them for Drupal 9. Do the same for your custom theme:
drupal-check -a web/themes/custom
In your custom modules, for a starter, change the version constraint from:
core: 8.x
to:
core_version_requirement: ^8 || ^9
It is harder than expected, and you should make sure all your contributed and custom modules are ready.
When you get a better understanding of composer, you'll realize what's going on.
For me also, this is a warning that you should use as least contributed modules as possible and stick to core!
Still not working? Look at this screencast, it can help you with overcoming your last issues.
Got the error below? Remove type3/... from your composer.json. Will come along with drupal/core-recommended (if necessary)
Can only install one of: typo3/phar-stream-wrapper[xxxx].
Enable verbose error reporting to debug "unexpected error" white screens: https://stefvanlooveren.me/blog/how-debug-and-enable-php-error-reporting-drupal-8
https://www.computerminds.co.uk/articles/apply-drupal-9-compatibility-patches-composer
https://medium.com/geekculture/7-tips-on-upgrading-from-drupal-8-to-drupal-9-648f519d6e7e