PHP 8.2 for MediaWiki developers
Thiemo Kreuz, November 2022
Read more »
PHP 8.2 is yet another update that's meant to be smaller but comes – again – with changes that might turn out to be quite impactful on a legacy system like MediaWiki. Let's see.
TL;DR: Log all notices, watch them, and rework code that dynamically appends properties to objects that aren't meant to be extended like that. Check if you rely on setlocale()
. Remove utf8_encode()
and utf8_decode()
. Scan your code for ${…}
in strings. Check your str_split()
.
In detail:
- You can't dynamically assign random properties to existing objects any more when the class doesn't allow it. Well, you still can but will get a deprecation warning. The plan is to make it fail hard in PHP 9.0.
stdClass
objects constructed via new stdClass()
or preferably (object)[]
will always be an exception, obviously.
While this is certainly a welcome update to the language it will have at least some impact on MediaWiki development. We occasionally use this language feature to e.g. attach singleton instances to existing objects they belong to. Here is an example where we already got rid of it. 😄️ And here is an example where we still do it. 🙄️ In almost all cases we need to replace what was never more than a hack on the callers side with either a WeakMap
, even simpler in-memory solutions like HashBagOStuff
, or – as done in the first example – MapCacheLRU
. I'm sure we will very rarely mark classes with #[AllowDynamicProperties]
, if ever.
There is no plan to ever remove the feature.
- The
"${var}"
string interpolation syntax is deprecated. Use "{$var}"
instead.
- String functions like
strtolower()
, ucfirst()
, and so on are no longer locale-sensitive. They will now always do the same canonical ASCII case conversion as if setlocale( LC_ALL, 'C' )
was set. If you have older code that doesn't work with UTF-8 but e.g. ISO-8859-1 or other 8-bit character sets and expects PHP to respect setlocale( LC_ALL, 'de_DE' )
, it won't any more. Use mb_strtolower()
and such instead.
Notable trivia: The RfC for this came from a well known long-term MediaWiki developer.
- The change above also affects functions that don't modify but compare strings to search or sort them, e.g. case-insensitive
stripos()
or when sort( …, SORT_FLAG_CASE )
is used. These might start to behave different in code that was written before UTF-8 became the standard. Code that expects PHP to respect setlocale( LC_ALL, 'de_DE' )
will effectively stop working in many situations. Look into mb_strpos()
and such instead.
strcmp()
, substr_compare()
and similar functions are now guaranteed to return -1, 0 and 1. Before any negative or positive value could have been returned. This change should usually not affect any existing code and isn't listed as backwards incompatible because of that.
- An entire class can be marked as 🔏️
readonly
now. This will also disable dynamic properties (see above).
- Traits can have constants now.
- It's now possible to combine union types (since PHP 8.0) and intersection types (since PHP 8.1).
true
is a new type. null
and false
already existed since PHP 8.0 but couldn't be used standalone, only as part of a union type. Now they can all be used standalone. Real-world use-cases for these should be incredibly rare, though.
iterable
exists since PHP 7.1. PHP 8.2 changes it to a built-in compile time alias for the union type array|Traversable
. This possibly affects error messages, but doesn't change how it behaves.
str_split( '' )
and mb_str_split( '' )
will now behave consistent and return an empty array when fed with an empty string instead of an unexpected and pretty much useless [ '' ]
array. Note this doesn't apply to explode( '' )
. This will still return [ '' ]
.
- Regular expressions now support:
- The so called »no auto capture« modifier
/n
at the end of a pattern turns all unnamed groups into non-capturing groups.
- The escape sequence
\0
can be used as a shortcut for the null character \x00
.
ini_parse_quantity()
can parse strings like '1M'
. I'm aware of at least one neat little function in MediaWiki that does exactly this since 2013 and could be replaced now.
idate()
supports the new format specifiers 'N'
for the ISO-8601 day of the week and 'o'
for the ISO-8601 year.
utf8_encode()
and utf8_decode()
are deprecated. Use mb_convert_encoding()
or iconv()
instead.
- Some weird callable syntax combinations like
'self::method'
or [ 'self', 'method' ]
😵💫️ are deprecated.
PHP 8.2 is scheduled for release in November 2022, will be actively supported for 2 years and continue to receive security updates until November 2025.
Older posts: