Problem/Motivation

Make sure Drupal 9 keeps being compatible with PHP 8.1. Work with dependencies as needed. See #3109885: [meta] Ensure compatibility of Drupal 9 with PHP 8.0 (as it evolves) for how we did it with PHP 8.0. PHP 8.1-alpha1 is now released, see https://www.php.net/archive/2021.php#2021-06-10-1

Proposed resolution

Figure out what breaks. Itemize and resolve one by one.

1. Dependency updates to support PHP 8

List of upstream updates in progress

List of upstream dependencies that are likely to lack PHP 8.1 support

Upstream fixes that are merged but need a release: NONE

Released but waiting composer update: NONE

DONE

2. Internal Drupal issues

Complete. See related issues side bar :)

Release notes snippet

Drupal 9.3.x is tested on PHP 8.1.

Issue fork drupal-3220021

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Gábor Hojtsy created an issue. See original summary.

Gábor Hojtsy’s picture

Version: 9.1.x-dev » 9.3.x-dev
Status: Active » Needs review
FileSize
473 bytes
Gábor Hojtsy’s picture

Issue summary: View changes

Fix backlink to PHP 8 issue.

andypost’s picture

Failures with reflection could use to extend core's wrapper created in #3156542: \ReflectionParameter::getClass() is deprecated in PHP 8.0

Gábor Hojtsy’s picture

Per @Mixologic earlier results are available at https://dispatcher.drupalci.org/job/drupal8_core_regression_tests/40398/... (while this one is still in the queue).

andypost’s picture

composer deprecation notice should be fixed in https://github.com/justinrainbow/json-schema/pull/666 and then propagated to composer, filed https://github.com/composer/composer/issues/9981

EDIT composer compatibility issue https://github.com/composer/composer/issues/9718 and another fix is https://github.com/justinrainbow/json-schema/pull/657

andypost’s picture

PHP Deprecated: Declaration of Drupal\Core\Template\Attribute::jsonSerialize() should be compatible with JsonSerializable::jsonSerialize(): mixed in /var/www/html/core/lib/Drupal/Core/Template/Attribute.php on line 372 could wait when core will require PHP 8 to add "mixed" to result of \Drupal\Core\Template\Attribute::jsonSerialize()

Ref https://www.php.net/manual/en/language.types.declarations.php#language.t...

andypost’s picture

Lots of Deprecated: Declaration of Doctrine\Common\Reflection\StaticReflectionClass::getName() should be compatible with ReflectionClass::getName(): string in /var/www/html/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php on line 28 require to file issues to doctrine

alexpott’s picture

Here's a start that allows some unit and kernel tests to run without error.

Symfony's session stuff is going to be fun and the Doctrine reflection stuff will be fun again - especially now that it is deprecated.

Status: Needs review » Needs work

The last submitted patch, 9: 3220021-9.patch, failed testing. View results

longwave’s picture

This is another reason to move forward with #3180351: doctrine/reflection is abandoned

longwave’s picture

Trying this locally via early support in ddev (https://github.com/drud/ddev-contrib/pull/141), the patch helps but then I am seeing a strange error with the autoloader after logging in - there is no reason I can see that this class can't be found:

NOTICE: PHP message: Error: Class "Drupal\Core\Logger\RfcLogLevel" not found in /var/www/html/drupal/core/includes/errors.inc on line 26 #0 /var/www/html/drupal/core/includes/errors.inc(60): drupal_error_levels()

Maybe I should just wait for a more stable release.

edit: turns out this was likely user error in my container setup and not a PHP or Drupal problem

andypost’s picture

Alpha 2 coming tomorrow

andypost’s picture

There's https://github.com/spiral/attributes a piolifill to use native attributes

longwave’s picture

behat/mink and masterminds/html5 both trigger PHP deprecations, so upstream will need fixes for those, or we need to work around them. We also need to catch PHP deprecations the same way we catch and pass on userland deprecations in TestHttpClientMiddleware otherwise any functional test that triggers a deprecation in the test site results in a hard fail.

I've skipped a number of PHP deprecations for the time being until we track down the source of each and fix them. Locally this gets some functional tests running, and even a few passing.

longwave’s picture

1) Drupal\Tests\media\Kernel\MediaEmbedFilterTest::testAccessUnpublished with data set "user can access embedded media" (true, true, Drupal\Core\Cache\CacheableMetadata Object (...), array(array('media/filter.caption')))
PHPUnit\Framework\Exception: Segmentation fault (core dumped)

I'm sure this will be fun to debug!

Mixologic’s picture

There's actually some tools built into drupalci to help with segfaults.

We build the php containers with the debug symbols, and whenever a segfault is detected, a GDB script runs and produces a backtrace of *where* in php the segfault occurred. Usually this is helpful for pushing things back upstream to PHP (we found so many with our testsuite that they delayed php7 by a couple of months to fix them all)

I would try submitting a patch with just that one test to see if you can cause it to segfault on the testbots, and there should be some data in the artifacts directory with details as to what caused the segfault.

alexpott’s picture

+++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
@@ -126,6 +126,15 @@ public static function getSkippedDeprecations() {
+      // PHP 8.1.
+      'strtolower(): Passing null to parameter #1 ($string) of type string is deprecated',
+      'stripos(): Passing null to parameter #1 ($haystack) of type string is deprecated',
+      'strlen(): Passing null to parameter #1 ($string) of type string is deprecated',
+      'preg_match_all(): Passing null to parameter #2 ($subject) of type string is deprecated',
+      'mb_strlen(): Passing null to parameter #1 ($string) of type string is deprecated',
+      'DOMElement::setAttribute(): Passing null to parameter #2 ($value) of type string is deprecated',
+      'DOMImplementation::createDocument(): Passing null to parameter #2 ($qualifiedName) of type string is deprecated',

I think we need to actually fix these. At least we have in the past.

longwave’s picture

We totally do, I was just trying to get closer to a green run first without those getting in the way, then hopefully we can pick these off one by one as we do with other deprecations.

longwave’s picture

Status: Needs work » Needs review
FileSize
41.21 KB

Added all the deprecations from the last run.

longwave’s picture

longwave’s picture

The bulk of this looks like this is going to be quite a laborious task of adding checks or casts around values passed to numerous PHP builtin functions :(

Additionally, any tests that use mikey179/vfsstream are failing with a deprecation warning due to https://github.com/bovigo/vfsStream/issues/252 - but upgrading that to 1.x-dev brings with it its own deprecation:

Using the "org\bovigo\vfs\vfsStreamWrapper" class is deprecated since version 1.7 and will be removed in version 2, use "bovigo\vfs\StreamWrapper" instead.

Finally, some uses of Prophecy also seems to be generating some deprecation warnings which then turn into a crash, e.g. $this->prophesize(MarkupInterface::class):

Return type of Double\MarkupInterface\P1::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[ReturnTypeWillChange] attribute should be used to temporarily suppress the notice

PHP Warning:  Uncaught Error: Object of class UnwindExit could not be converted to string in /var/www/html/drupal/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php(49) : eval()'d code:2

PHP Fatal error:  During inheritance of JsonSerializable: Uncaught  in /var/www/html/drupal/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php(49) : eval()'d code on line 2
longwave’s picture

Upgrading Twig for https://github.com/twigphp/Twig/issues/3534 helps a lot.

andypost’s picture

Another option is setting for phpunit https://github.com/twigphp/Twig/issues/3534#issuecomment-859866066

convertDeprecationsToExceptions="false"

longwave’s picture

With Symfony 4.4.26 we can drop the HttpFoundation workarounds: https://github.com/symfony/symfony/pull/41495

I guess we might need to sprinkle our own code with #[ReturnTypeWillChange] to start with.

alexpott’s picture

Note this is an xpost with #26...

@longwave I'm not sure the best to get green is to skip all the errors. That's not how we've done it before. On the other issues like this we've worked through each error till we get each test green.

Upgrading symfony/http-foundation and masterminds/html5 fixes quite a bit too. We should do the same as Twig and Symfony and us the PHP annotation to indicate the return type will change - i.e. #[\ReturnTypeWillChange].

The patch attached has a green \Drupal\Tests\system\Functional\Module\InstallUninstallTest

Opened https://github.com/symfony/symfony/pull/42074 for one deprecation.
We need to open a PR against Mink too.

longwave’s picture

@alexpott because there are so many deprecations my intent was to get it green with skips (or at least some numbers reported back!) and then try to fix them one by one in spinoff issues, a bit like we have with PHPUnit deprecations - otherwise I feel this patch is going to become enormous very quickly

Status: Needs review » Needs work

The last submitted patch, 27: 3220021-25.patch, failed testing. View results

alexpott’s picture

I think we need to ask for the PHP 8.1 fix for bovigo\vfs to be backported to the version we're on - or at least more compatible with it...

Drupal\Tests\Component\Gettext\PoStreamWriterTest::testCloseException
Error: Class "bovigo\vfs\vfsStreamFile" not found

... that's going to break a lot of contrib.

alexpott’s picture

@longwave I think it is fine for this patch to get enormous - it's a scope of work and not much of it is worth carving into separate issues really. I'm not convinced that lots of little issues for each string cast or ?? '' in a string function is helpful. Things like the syslog config on install fix - that definitely should be it's own issue.

longwave’s picture

The bovigo\vfs issues are a bad find/replace on my part, pushed another set of fixes for this that should now be complete - worth spinning this off to its own issue and getting it committed?

alexpott’s picture

@longwave we need a bovigo\vfs release before we should do that. What would be good is to update our 9.3.x dependencies now... because that'd get us a couple of fixes.

longwave’s picture

Oh yeah, 1.6.7 doesn't include the new namespaces. https://github.com/bovigo/vfsStream/issues/252#issuecomment-836191861 notes there will be a new 1.6.x or 1.7.x later this year.

longwave’s picture

Some of the exception changes overlap with #3209619: [Symfony 6] Passing null as $message to Symfony exception constructors is deprecated, pass an empty string instead but I think there might be subtle BC breaks:

-  public function __construct(CacheableDependencyInterface $cacheability, $message = NULL, \Exception $previous = NULL, $code = 0) {
+  public function __construct(CacheableDependencyInterface $cacheability, $message = '', \Exception $previous = NULL, $code = 0) {

What if someone throws CacheableAccessDeniedHttpException with no message, and later catches it and checks $message === NULL?

alexpott’s picture

Re #35 I think think we're going to have that kind of problem. Imo checking for a message === NULL is just not supported. Use empty(). It's great that #3209619: [Symfony 6] Passing null as $message to Symfony exception constructors is deprecated, pass an empty string instead exists to discuss this already. The NULL exception message is one obvious issue to break out.

alexpott’s picture

Issue summary: View changes

Adding some info about dependency updates - more to be added.

alexpott’s picture

Issue summary: View changes

Adding more upstream issues.

alexpott’s picture

Issue summary: View changes
Status: Needs work » Needs review

The remaining fails are:

  • Drupal\BuildTests\Composer\Template\ComposerProjectTemplatesTest - due to using development vendor code - will be resolved once Twig is released
  • Drupal\Tests\Component\Datetime\DateTimePlusTest and Drupal\Tests\Core\Datetime\DrupalDateTimeTest - due to a PHP bug - https://bugs.php.net/bug.php?id=81273

Now it's time to create some Drupal issues for the runtime fixes here.

alexpott’s picture

Issue summary: View changes
longwave’s picture

To sidestep the Guzzle issue, we can use a shim. Guzzle doesn't use use function or prefix its function calls with \ - so we can override http_build_query() in the GuzzleHttp namespace, and intercept and rewrite the calls as necessary. Something like:

namespace GuzzleHttp;

function http_build_query($data, $numeric_prefix, $arg_separator, $encoding_type) {
    \http_build_query($data, is_null($numeric_prefix) ? '' : $numeric_prefix, $arg_separator, $encoding_type);
}
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
longwave’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
andypost’s picture

Looking at https://github.com/php/php-src/blob/php-8.1.0beta1/UPGRADING#L486-L489

ReflectionProperty::setAccessible() and ReflectionMethod::setAccessible()
no longer have an effect. Properties and methods are always considered
accessible through reflection.
RFC: https://wiki.php.net/rfc/make-reflection-setaccessible-no-op

there's current core usage

core9$ git grep setAccessible |wc -l
160

I bet it needs separate issue as mostly tests are affected

longwave’s picture

@andypost we can't change that until we require minimum PHP 8.1 though?

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
andypost’s picture

Additionally pecl yaml extension fails to build with PHP 8.1 so d-org infra can't upgrade to beta

Filed pr to fix that https://github.com/php/pecl-file_formats-yaml/pull/60

andypost’s picture

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
andypost’s picture

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes

Prophecy has a PR for 8.1 compatibility - https://github.com/phpspec/prophecy/pull/533 - I've applied it as a patch via our composer phpunit update commands for now and it is working.

andypost’s picture

daffie’s picture

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes

Updating issue summary with the info about what would prevent an install on PHP 8.1 due to PHP requirements. Note that these upper constraints don't affect drupal core dev because set the platform in the root composer json but it will affect anything built from core recommended and the other project templates.

alexpott’s picture

Issue summary: View changes
andypost’s picture

andypost’s picture

Filed #3230562: Update dependencies for Drupal 9.3 as a lots of updates arrived

alexpott’s picture

Issue summary: View changes

Merged in the Symfony updates fwiw.

alexpott’s picture

Issue summary: View changes

Updating list of Drupal issues.

Gábor Hojtsy’s picture

catch’s picture

Issue summary: View changes
andypost’s picture

alexpott’s picture

alexpott’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
daffie’s picture

alexpott’s picture

Merged 9.3.x - there's been some progress. For our dependencies:

  • we're still using dev versions of behat/mink behat/mink-selenium2-driver mikey179/vfsstream - these need releases
  • we have a replacement class for laminas/laminas-feed
daffie’s picture

Issue summary: View changes

#3232571: Update dependencies for 9.3.x has landed and with that the 2 problems with Prophecy have been fixed.

daffie’s picture

Issue summary: View changes

The 2 twig fixes have had a release and landed in the vendor directory.

alexpott’s picture

Issue summary: View changes

Making the why-not command correct.

daffie’s picture

Status: Needs review » Needs work

PHP 8.1 RC2 is out. See: https://www.php.net/archive/2021.php#2021-09-16-1
Could we get a testbot run with 8.1 RC2?

andypost’s picture

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
Status: Needs work » Needs review

I've updated the issue summary to point to the github issues asking for a PHP 8.1 compatible stable release for behat/mink, behat/mink-selenium2-driver and mikey179/vfsstream .

daffie’s picture

alexpott’s picture

Issue summary: View changes

@daffie thanks for updating the issue summary. 3224941 doesn't need fixing yet - it's open for when core's minimum PHP version is PHP 8.1 - feels quite a way off :)

daffie’s picture

alexpott’s picture

daffie’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
daffie’s picture

andypost’s picture

daffie’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
daffie’s picture

alexpott’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
daffie’s picture

Issue summary: View changes
andypost’s picture

andypost’s picture

andypost’s picture

Filed upgrade for SF (has some 8.1 fixes) and the rest #3239772: Update dependencies for Drupal 9.3

daffie’s picture

Issue summary: View changes
andypost’s picture

andypost’s picture

PHPCS also should create new release soon as milestone finished https://github.com/squizlabs/PHP_CodeSniffer/milestone/26

andypost’s picture

Lots of follow-ups files by Alex

Meantime I find this 2 issues are priority as prevents lots of noise running tests

- #3240191: \Drupal\KernelTests\KernelTestBase::bootKernel() causing deprecations in PHP 8.1
- #3240192: \Drupal\user\AccountForm::buildEntity() causing deprecations in PHP 8.1

daffie’s picture

PHP has released PHP 8.1 RC3. See: https://www.php.net/archive/2021.php#2021-09-30-1

daffie’s picture

We are getting a number of explode() warnings: "Exception: Deprecated function: explode(): Passing null to parameter #2 ($string) of type string is deprecated Drupal\comment\CommentViewBuilder->buildComponents()() (Line: 127)"

Could we do a testbot run with PHP 8.1-RC3.

andypost’s picture

Just queued test run on updated images (labels are not deployed yet)

00:27:50 php -v

00:27:51 PHP 8.1.0RC3 (cli) (built: Oct  1 2021 18:22:46) (NTS)
00:27:51 Copyright (c) The PHP Group
00:27:51 Zend Engine v4.1.0RC3, Copyright (c) Zend Technologies
00:27:51     with Zend OPcache v8.1.0RC3, Copyright (c), by Zend Technologies
andypost’s picture

andypost’s picture

andypost’s picture

andypost’s picture

Issue summary: View changes
andypost’s picture

Issue summary: View changes
andypost’s picture

andypost’s picture

7 new child issues filed

alexpott’s picture

I *think* that we now have sub issues for every single change in the meta merge request. The only thing we're missing is a Mink and a MinkSelenium2Driver upgrade issue. The Mink maintainer has said that there will be a release soon as I've resolved their blockers for that.

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes

Updating outstanding list.

andypost’s picture

Only 3 issues left!

alexpott’s picture

alexpott’s picture

Issue summary: View changes
andypost’s picture

There's phpcs release compatible with 8.1

https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.6.1

alexpott’s picture

@andypost let's wait for behat/* until we create a dependency update.

andypost’s picture

Issue summary: View changes
andypost’s picture

I filed another child issue #3242889: Update dependencies for 9.3.x

we could re-purpose it for other updates but I get locally still 2 deprecation notices

alexpott’s picture

Issue summary: View changes
alexpott’s picture

Issue summary: View changes

Green at last.

catch’s picture

alexpott’s picture

Issue summary: View changes
Status: Needs review » Fixed

We are done! PHP 8.1 testing has been enabled for 9.3.x on commit.

All child issues that are required for PHP 8.1 compatibility are fixed, therefore, we can move this meta to fixed as it is complete.

mondrake’s picture

🎉 great work, thanks a lot to all involved!

andypost’s picture

I think daily or weekly run of CI 8.1 could be enabled to prevent regressions

andypost’s picture

Gábor Hojtsy’s picture

@andypost: as @alexpott pointed out in chat, as per https://www.drupal.org/node/3060/qa 8.1 is already being tested on each commit not just daily or weekly. That should definitely help avoid regressions.

andypost’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

JayKandari’s picture

After latest upgrade to 9.3.7 with php 8.1, got the strange error mentioned in #12
NOTICE: PHP message: Error: Class "Drupal\Core\Logger\RfcLogLevel" not found in ...

Did composer install after removing `core` && `vendor` folders as well. same issue.

EDIT: Fixed this by restarting `service php8.1-fpm reload`

quietone’s picture

I just ran into the error message about RfcLogLevel too. See #12.

In my case a Commerce Migrate functional test was working on 9.4.x on one ddev environemnt and failing in another ddev environment The difference was that the working one was using composer 2, composer_version: "2" in .ddev/config.yaml and the failing one had no configuration value for composer_version. Once I

Mingsong’s picture

Fatal error with PHP 8.1 and Drupal 9.3.12:

Uncaught TypeError: htmlspecialchars() expects parameter 1 to be string, array given in Drupal\Component\Utility\Html::escape() (line 424 of /app/web/core/lib/Drupal/Component/Utility/Html.php)

If the field value is empty (''), then following twig template code will triggle that fatal error.

{% set body = {
  '#type': 'processed_text',
  '#text': paragraph.field_body.value,
  '#format': paragraph.field_body.format,
} %}

{{ body }}
larowlan’s picture

@Mingsong try {{ paragraph.field_body.processed }}

Mingsong’s picture

Thanks @Lee Rowlands for prompt response.

Yes, using 'processed' instead of the render array will avoid the fatal PHP error.