What's new in PHP 8.1
Thiemo Kreuz, February 2022
Read more »
While our Wikimedia servers are stuck with PHP 7.2 for a little longer, I'm very much looking forward to the day we can start using the new features every later PHP version came with. Continuing a series of similar posts here is my personal list of highly anticipated changes and features that are new in PHP 8.1, compared to PHP 8.0. As always in order of personal preference.
TL;DR: Enums. Intersection types with A&B
. readonly
class properties. never
return type. array_is_list()
. First-class callables with foo(...)
.
Update from November 2022: As it turned out the by far biggest impact on MediaWiki was because built-in string functions like trim()
, substr()
, preg_match()
, and many, many more stopped accepting null. This didn't only affect problematic code we are happy to fix. The deprecation also broke a lot of code that used the behavior as a feature. For example, an if ( trim( $input ) === '' )
check worked just fine with null
. Luckily we also got convenient features like ??
(since PHP 7.0) and ??=
(since PHP 7.4) that made the migration less painful.
While putting this together I also stumbled upon PHP.Watch, a much more detailed resource for exactly what I do here. Written by a single person and going into way more detail than you ever asked for. 👍 Which leaves me with the task of compiling a short version that's focused on the MediaWiki development I mostly care about. Let's go.
- PHP finally got enumerations. I was waiting for this for a very long time. Before we had to give global constants a prefix (like PHP itself does) to not get lost, or put them in an »interface« that doesn't do anything but host a set of related constants. Still what PHP 8.1 gives us now is not that different. Enums in PHP are actually »built on classes and objects« and behave a lot like them. They can even have methods, but no state.
- Array unpacking now supports string-keyed arrays as well. The semantics follow strictly what
array_merge()
does. These two lines do the same:
$result = array_merge(
[ 'a' => 0 ],
$arrayA,
$arrayB
);
$result = [
'a' => 0,
...$arrayA,
...$arrayB
];
array_is_list()
is a fast, native way to check if an array is compatible with a for
loop. You can force any array to be such a list by running it through array_values()
.
- Pure intersection types require a value to satisfy multiple type constraints the same time. A good example is
Iterator&Countable
. Note that union types with the syntax Iterator|Countable
exist since PHP 8.0.
never
(previously known as »noreturn«) is a strict return type for functions that, for example, are guaranteed to throw an exception and never give the control flow back to the caller. It's meant to replace @return noreturn
comments you might have used before.
- Class properties can be marked as
readonly
. These can be initialized once from anywhere within the class (doesn't need to be the constructor) and never changed again.
- The
new
keyword can be used in initializers, most notably in method signatures. A good example is public function __construct( Logger $logger = new NullLogger() )
. Combining this with constructor property promotion is possible.
- We got a new syntax called »first-class callables« that allows us to replace arrays like
$callback = [ $this, 'methodName' ];
with $callback = $this->methodName(...);
and then call it with $callback();
. Note that the three dots are the actual syntax for this, similar to the variable-length arguments syntax methodName( ...$args )
we have since PHP 5.6.
- The
final
modifier can be used on class constants. Such a constant can't be changed in subclasses.
htmlspecialchars()
and such will not return an empty string any more when the input is not valid UTF-8. They now use the ENT_SUBSTITUTE
mode by default. This mode replaces bad characters with the Unicode replacement character � (U+FFFD).
- A
static
variable in a method will now behave like a static property and be visible to subclasses that override the method.
- You should check your code for usages of
is_resource()
and replace it with checks for false
whenever possible. The reason is that more features don't return numeric resource identifiers any more, but objects.
Some more things that are most probably mistakes in your code will spit out deprecation warnings now. For example, $array[ 1.5 ]
won't silently drop the .5
any more. Internal functions will not silently accept null
any more when a parameter is not really nullable. While one might want to classify these as (future) breaking changes, personally I think of these more as issues with my code I want to fix.
PHP 8.1 was released in November 2021, will be actively supported for 2 years and continue to receive security updates until November 2024.
Older posts: