Install
To start a new Drupal project with version 9.3.0:To update your site and all dependencies to the latest version of Drupal:
To update your site to this specific release:
Using Composer to manage Drupal site dependencies
Downloads
Release notes
This is a minor version (feature release) of Drupal 9 and is ready for use on production sites. Learn more about Drupal 9 and the Drupal core release cycle.
This minor release provides new improvements and functionality without breaking backward compatibility (BC) for public APIs. Note that there may be changes in internal APIs and experimental modules that require updates to contributed and custom modules and themes per Drupal core's backward compatibility and experimental module policies.
Minor releases may include string changes and additions. Translators can review the latest translation status on localize.drupal.org.
Drupal 9.3.x contains new features, and should be the target for new site development. Drupal 9.2.x will continue to have security support until June 2022.
9.1.x and 8.9.x will no longer receive security support, so sites on a Drupal 8 or 9 version earlier than 9.2.x should upgrade to a supported release as soon as possible.
Platform requirements
From Drupal 9.3, PHP version 8.0 or higher is recommended. PHP 7.3 and higher remain supported. Drupal 10 will require at least PHP 8.0.
Important update information
Updating from Drupal 8
For information on updating from Drupal 8 to Drupal 9, see Upgrading a Drupal 8 site to Drupal 9.
Upgrading from Drupal 6 and 7
Drupal 6 and 7 users can continue to migrate to Drupal 9 directly. The migration paths from Drupal 6 and Drupal 7 to Drupal 9 will remain supported throughout Drupal 9's release cycle.
Browser requirements changes
Drupal core previously declared support for Opera Mini in 'Extreme Data Savings' mode, due to an issue with how the service Can I Use... documents the browser's features. Drupal never actually supported this mode, so the declaration has been removed. Opera Mini in 'High Data Savings' mode, as well as Opera Mobile (a different browser altogether), are unaffected.
Configuration sort ordering change
Configuration is now always sorted by the order defined in its schema. You should always re-export configuration and commit it to version control after running updates. See the change record on config mapping sorting for more recommendations.
User role dependencies and database changes
-
Each user role now depends on the modules that provide the role's permissions. This means that permissions will be automatically cleaned up when a module is uninstalled. Additionally, if a custom or contributed module uses a permission callback, see how to add additional dependency to the callback's return value. Existing roles will be updated to remove permissions that do not exist and dependencies will be added.
-
The users table will be updated to change the uid column to a true serial field. See the change record on user table sorting for more information.
Theme system and template changes
-
field--node--title.html.twig
,field--node--created.html.twig
, andfield--node--uid.html.twig
have been modified to render these fields as they are configured by the site builder for sites that allow configuring the display of these fields. Themes that include these templates should add this change to them as well. -
Shortcut icons are now output as
<link rel="icon">
as per the HTML spec instead of<link rel="shortcut icon">
.
The change record has details of the shortcut markup change. -
Submit buttons themed as
<button type="submit">
elements now trigger AJAX within Views exposed forms, just like they do when themed as<input type="submit">
elements. This now matches the behavior of Drupal 7 Views, fixing a regression from Drupal 8 and earlier versions of Drupal 9. -
Drupal-specific
<link>
tags have been removed from node and taxonomy term pages to improve performance. There are no known uses of these tags in contributed or custom code.<link rel="canonical">
and<link rel="shortlink">
tags remain, and have been extended to cover all entity types.
Form field data changes
-
Most file URLs will now use relative instead of absolute links, after refactoring of the file generation APIs.
-
Field labels can now be up to 255 characters long. This has no impact on the API, but requires attention in admin themes to account for the longer possible label length.
-
Block plugin forms no longer get a
'block_theme' key
in form state because it was unreliable. This may require changes to form code that interacted with this key. See the change record on the 'block_theme' key removal for more details.
Warning added for missing PostgreSQL requirement
In preparation for Drupal 10 PostgreSQL requirements, sites running PostgreSQL without the pg_trm
extension will begin to see a warning in the status report when it is not installed.
JSON:API data changes
drupal_internal__target_id
has been added to JSON:API responses. See the change record on JSONAPI addition the addition for more information.
Change to middlewares
Some module developers may be affected by the fact that GuzzleMiddlewarePass
has been removed in favor of the generic TaggedHandlersPass
, code interacting with GuzzleMiddlewarePass
should use TaggedHandlersPass
instead.
See the change record on the change to use TaggedHandlersPass
for details.
Core module deprecations and changes to the standard install profile
The Quick Edit module is slated for removal from core in Drupal 10. To this end, Quick Edit has been removed from the Standard profile in Drupal 9.3.0. This change does not affect existing sites, only new sites installing the Standard profile for the first time. For more information, see the change record on Quick Edit's removal from the Standard profile.
CKEditor 5 module added as a new experimental replacement for CKEditor 4
CKEditor 4 will reach end-of-life in 2023. An experimental module for CKEditor 5 has been added and will replace CKEditor 4 in Drupal 10.
CKEditor 5 differs significantly from CKEditor 4, so sites and modules should begin testing with it now in preparation for Drupal 10's release next year. The module is experimental and therefore not yet intended for production use.
Testing CKEditor 5
Back up your site data and configuration before beginning testing. We recommend following the testing instructions in the change record. Test:
-
The automatic content upgrade path: You should get the equivalent CKEditor 5 configuration created automatically: toolbar, plugin settings, and so on. Messages will appear upon switching that explain what happened and why. Verify that the messages and generated configuration are correct.
-
The editing experience: Verify that the default CKEditor 5 configuration works as you need and expect. For example, the linking experience should be improved, uploading images is much faster, and so on.
-
Your existing content: When you edit existing content with CKEditor 5 and save it, verify that the resulting markup looks as you expect, and that no data is lost.
Upgrading contributed modules to CKEditor 5
The CKEditor 5 module can be also used for updating modules extending CKEditor 4 to be compatible with CKEditor 5. Documentation is available to help contributed module owners with upgrading their CKEditor 4 integration modules to CKeditor 5.
We recommend that contrib authors begin work on this as their schedules permit, since CKEditor5 had many differences from CKEditor 4.
- Meta issue of contrib modules being ported: #3207845: [META] Port some initial CKEditor 4 plugin integration modules to CKEditor 5
- Examples of complex CKEditor 4 modules updating to CKEditor 5 compatibility:
Automated testing changes
-
FunctionalJavascript tests now automatically check to see if any JavaScript errors have been thrown during the test's execution. In Drupal 10, this will cause the test to fail, while in Drupal 9.3, a deprecation warning is issued for tests that pass despite the presence of JavaScript errors. See the change record on this JavaScript testing change for details.
-
The
cspell
automated spellchecking utility used by Drupal core has been updated from 4.2.8 to 5.6.6. This should only affect patch development and testing workflows.
Removed dependencies
While we do not normally remove Drupal core dependencies in minor releases, Drupal core's dependencies on fabpot/goutte
and behat/mink-goutte-driver
have been removed in 9.3 because core does not use them and because they prevent us from allowing forward-compatibility with Guzzle 7 and PHP 8.1. If your site or module uses either of these dependencies, be sure they are added to the project's composer.json
. (Change record on Goutte's removal.)
Deprecated dependencies
-
jquery.once
has been deprecated as a Drupal dependency. Contributed modules should update to use the new once.js core JavaScript library. See the change record onjquery.once
for details. -
The package
Doctrine/reflection
is abandoned and the parts Drupal core relies on have been copied toDrupal\Component\Annotation\Doctrine
. The package will be removed from Drupal 10. Contrib and custom code should update any code that uses the package and remove the dependency as indicated in the
change record on the removal of Doctrine/reflection.
JavaScript Dependency updates
- CKEditor 4 has been updated from 4.16.2 to 4.17.1 to address a security vulnerability. (Sites are recommended to beginning testing with CKEditor 5 as soon as possible.)
js-cookie
has been updated from 3.0.0-rc0 to 3.0.1.popperjs
has been updated from 2.9.2 to 2.10.2.sortable
has been updated from 1.13.0 to 1.14.0.tabbable
has been updated from 5.2.0 to 5.2.1.- Numerous development JavaScript libraries (used in the support coding standards check and of CKEditor 5) have been updated to the latest patch versions.
PHP Dependency updates
Updated PHP dependencies
Email validation change for dependency update
egulias/email-validator
has been updated from version 2 to version 3.1.2, because version 2 will not have security coverage in two months. This upgrade will result in stricter validation of e-mail addresses, for example example@examp&
will now be rejected, when it was previously treated as valid with egulias/email-validator
2.
If an invalid e-mail address has been entered into the system, it will fail validation the next time it is saved, for example when editing a user account. When this happens, the user will only be able to continue with saving the form by changing the e-mail address to a valid format. No automatic changes to user data will be made. Where user registration requires an e-mail verification step, it is very unlikely that any existing user accounts will be affected, since they must have been able to receive an e-mail in order to register successfully in the first place. Additionally, most modern browsers provide client-side validation on e-mail form inputs. However, this could affect test content on local development environments and other edge cases.
If a site experiences problems from this update, it is still possible to downgrade back to egulias/email-validator
2 via composer (assuming that you're not using drupal/core-recommended
.
Additionally, the API for the EmailParser
class provided by this library has changed:
Before:
$emailParser = new EmailParser(new EmailLexer());
$result = $emailParser->parse('test@test'); // result is array with
After:
$emailParser = new EmailParser(new EmailLexer());
$emailParser->parse('email@test'); // result is an object that implements Egulias\EmailValidator\Result\Result interface
$emailParser->getDomainPart(); // this is how you get the domain part
PHPUnit not yet updated to PHPUnit 9
Minor-version dependency updates
For minor-version dependency updates, it is recommended to consult the respective release notes to ensure no breaking changes will affect your site.
- Laminas components have received minor-level updates for compatibility with the latest PHP versions.
composer/ca-bundle
has been updated from 1.2.9 to 1.3.1phpdocumentor/type-resolver
also received a minor-version update from 1.4. to 1.5.0- Drupal's dependencies for
symfony/phpunit-bridge
,symfony/var-dumper
, andsymfony/mime
have been updated from Symfony 5.3.0 to 5.4.0.
PHPUnit 9 is not yet available, so PHPUnit has been updated to the latest patch-level version, 8.5.21. However, phpunit/phpunit
and symfony/phpunit-bridge
also received patch-level updates to the latest versions. Related dependencies including phpdocumentor/reflection-docblock
, behat/mink
, and phpdocumentor/type-resolver
have received updates to new minor version in preparation for upcoming releases .
Patch-level updates
Coding standards changes
-
In order to limit Drupal core's dependency on jQuery for forward-compatibility with future versions, the
eslint core-js-passing
config now includes the eslint-plugin-jquery plugin.
Currently, only a small number of the available rules ineslint-plugin-jquery
are enabled; these are the rules that check for jQuery features not used by core.As core eliminates uses of a given jQuery feature (typically because modern ES6 JavaScript has native replacements), additional
eslint-plugin-jquery
rules can be enabled. This will prevent those jQuery features from being reintroduced. For more information, review Eslint rules added to limit new jQuery usage for future compatibility <Drupal.Commenting.FunctionComment.MissingParamComment
has been enabled.Drupal.NamingConventions.ValidGlobal
has been enabled.
Known issues
- #3254403: system_post_update_sort_all_config can exhaust PHP memory in 9.3.0 because processing is not batched has been resolved and is available from the development branch until 9.3.1's release in January.
- #3253889: `?check_logged_in=1` causes `TrustedRedirectResponse` to fail has also been resolved, and will be included in the 9.3.1 release in January
- Views using the 'use field templates' setting may error due to a change introduced in 9.3.0. A fix for this regression is in progress
- The generated ID may change for views blocks work is under way to find the cause of this regression
Search the issue queue for known issues.
All changes since Drupal 9.3.0-rc1
- Issue #3251034 by lauriii, bnjmnm, longwave: Core Yarn watch builds CK5 plugins differently than yarn build
- Revert "Issue #2934995 by benjifisher, larowlan, paulocs, AaronMcHale, vikashsoni, danflanagan8, Berdir, SKAUGHT, alexpott: Add a "Manage permissions" tab for each bundle that has associated permissions"
- Issue #3252214 by Spokje: Move tests for integrations between QuickEdit and CKEditor5 into QuickEdit so that it can more easily be moved into contrib
- Issue #2886615 by scott_euser, clemens.tolboom, quietone, joachim, alexpott, Lendude: comment_empty_title_test has invalid hook
- Issue #2925203 by alexpott: LocaleConfigSubscriber can result in data loss during install
- Issue #2871357 by alexpott, kriboogh: Installer tasks using multiple batch sets in non-interactive mode do not get executed
- Issue #3251625 by alexpott, Berdir: Including settings.php a second time and without same context can result in errors
- Issue #3251768 by longwave: Update Symfony 5 dependencies to 5.4.0