Fooman

Php 8.1 gotchas for Magento developers




We have been working hard behind the scenes since the first Magento 2.4.4 beta releases to be able to support Magento 2.4.4 including support for Php 8.1 from the day of the general release. There is still a few places where we need to upload the latest releases right now like Magento Marketplace, but we got there:

We are pleased to say that all our extensions have been tested and updated to work with Magento 2.4.4 including Php 8.1 support from day 1.

Every Magento release brings with it it's own set of changes. Some more relevant to our extensions than others. From the Magento side the main change affecting us was the removal of email template processing that was started back with Magento 2.3.4. The removal of the legacy resolver meant some of our internal processes for generating the html behind our pdf extensions had to be adapted. The updated implementation should be invisible to most users but do let us know if you have done extensive customisations of any of our pdf extension (any theme adaptations are unaffected).

If you have been using custom implementations of your own, including heavy use of Magento objects as variables in your templates this would be an area to check as part of your 2.4.4 upgrade.

Php 8.1

The bigger changes this time around are due to the introduction of support for php 8.1. As the previous highest supported php version by Magento is 7.4 this jump also includes the changes introduced by php 8.0. (Adobe chose to not support 8.0 as there is not much time left in active support by php). I have found the following articles on Stitcher.io useful to give a summary of what changes are brought on by php itself.

One would usually expect the major version increase to be the trickier one to handle, however in our experience the following changes introduced by Php 8.1 caused issues across most of our extensions. One of the things I have learned over the years is that while technically a deprecation notice (in other words a heads up of something is going to break at the next major release) should in theory not be something that requires immediate attention in reality it does require handling from our side straight away. There are just too many environments/set ups running with deprecation notices on for this to cause a stop execution of the php script.

Passing null to parameter #1 ($string) of type string is deprecated

The above deprecation notice is what we have seen the most across the board. A lot of the built in php functions that handle strings are now no longer accepting null as input, for example functions like trim, str_replace and json_decode would error out. There are lots of ways to get caught in this as a Magento developer. For example one might run explode on a list of bcc email addresses provided through an admin setting. In the past if the setting was not set without a default value the code would just continue, now if would error on the explode(null) part.

Another one to keep in mind is that the almighty DataObject can easily provide nulls for anything that does't yet have a value:

protected function _getData($key)
{
    if (isset($this->_data[$key])) {
        return $this->_data[$key];
    }
    return null;
}

The fixes themselves are usually minor and can take the form of adding an extra guard clause like

$formData = json_decode($registry->getDataRule(), true);

to

if ($registry->getDataRule()) {
    $formData = json_decode($registry->getDataRule(), true);
    $form->addValues($formData);
}

or casting to a string

$pageName = trim($customPageName);

to

$pageName = trim((string) $customPageName);

The hard part is trying to find all the code paths that could result in a null getting passed into one of those php functions. Good testing coverage helps.

[ReturnTypeWillChange]

There was a good discussion on Twitter the other day around the benefits of using a bounded version range in your composer.json require section for php rather than leaving it open ended. This change is a good example of why one should be cautious about supporting future php versions without knowing what they include. For example if in the past you implemented your own implementations of php's standard \ArrayAccess class with php 8.1 the method signatures changed from

interface ArrayAccess {
    /* Methods */
    public offsetExists($offset)
    public offsetGet($offset)
    public offsetSet($offset, $value)
    public offsetUnset($offset)
}

to

interface ArrayAccess {
    /* Methods */
    public offsetExists(mixed $offset): bool
    public offsetGet(mixed $offset): mixed
    public offsetSet(mixed $offset, mixed $value): void
    public offsetUnset(mixed $offset): void
}

The use of mixed in particular poses challenges to php developers that want to support multiple versions of php at once with the same code base as the type mixed was only introduced with php 8.0. The escape hatch that is included is to use a special attribute #[ReturnTypeWillChange] - this will suppress the message until php 9.0 and is safe to use on earlier versions of php as it would just be considered a comment.

MyClass implements ArrayAccess {
    #[\ReturnTypeWillChange]
    public offsetGet($offset) {
    }

Happy updating. With the removal of most of the vendor bundled extensions in Magento 2.4.4 and the support of php 8+ this release certainly feels snappier during our time working with it.

Kristof Ringleff

Kristof Ringleff

Founder and Lead Developer at Fooman

Join the Fooman Community

We send our popular Fooman Developer Monthly email with Magento news, articles & developer tips, as well as occasional Fooman extension updates.