Thiemos Archiv

How to prepare your codebase for PHP 8

PHP 8 is planned to be released in November 2020. And while you might want to wait a few weeks or months before you start updating your production servers, you will definitely need to do it in November 2022 when all PHP 7 support ends.

The changes in PHP 8 are rather significant, compared to all previous releases – even compared to PHP 7.0. Sure, getting rid of register_globals was an enormous change. But it took a very long time, dating back as far as 2001, when $HTTP_POST_VARS was introduced as a first attempt to solve the problem. PHP 8 gets rid of more confusing, sometimes embarrassing design mistakes in a shorter time.

I compiled the following list from the work-in-progress upgrade notes with MediaWiki development in mind where we already have rather high standards.

  • You can't have functions or methods with the name match. That's a problem.
  • Old-style constructors where the constructor does have the same name as the class won't work any more.
  • Non-static methods can not be called statically any more, i.e. you can't have self::…() calling a method that is not marked as static. This is not easy to find in existing code, but there are tools to help you, e.g. Phan.
  • The operator precedence changed a bit. Oh, wait, what? That's huge! Much more than you might think. The order in which operators are executed is a very, very basic building block of any programming language. But it changed. When string concatenation is used together with addition, subtraction, or bitshifting operators, and you don't have enough brackets, your code might do something else now. There is no safe way you can predict how the result of an operation will change from PHP 7 to 8, without actually executing it. I hope you have tests. Heck, it's almost like PHP 8 is a different language than PHP 7 – and yea, it actually is.
  • Weak comparisons that include strings, integers, and/or numeric strings behave different. For example, 2 == "2foo" won't be true any more. 0 == "foo" was true before, but isn't any more. I'm not sure if 0 == "" changed as well. Even if you do not have any code that explicitly relied on this, you might still have users that did – kind of exposing a bug in PHP. Be prepared to have users complaining about certain inputs suddenly doing something else.
  • implode() with the two parameters in reverse order doesn't work any more. You should have got a deprecation warning since PHP 7.4.
  • array_key_exists() won't work on objects any more. To be honest I don't know how you can find this if you don't have proper test coverage. Luckily it's extremely easy to fix. Just replace it with property_exists(), or the more common isset().
  • When you create an array with -2 or lower as the first index, the next auto-index won't be 0 any more. For example, after $array = [ -2 => 'first' ]; $array[] = 'next'; the array contains [ -2 => 'first', -1 => 'next' ]. In earlier versions it was [ -2 => 'first', 0 => 'next' ]. I really hope you don't have code that relies on this behavior.
  • Array access via $array{0} isn't possible any more. Just use square brackets.
  • The tokenizer will read namespaced names as a single token now, instead of a sequence of backslashes and strings. This is relevant for many of the custom PHPCS sniffs we maintain. It shouldn't be that hard to make our code compatible with both. Again, test coverage is key. Later, when we drop PHP 7 support, we can even remove quite some code.
  • Regular expressions (PCRE) could have an uppercase /X modifier before. This modifier can't be specified any more. Instead, it's behavior is now the default: when you accidentally use an escaped character like \q in your pattern, but this character doesn't have a special meaning, it will no longer act like a literal "q" in your pattern, but be reported as an error. The list of characters that currently have a meaning – according to the manual – is ABDEGHKPQRSVWZabcdefhnprstvwxz.
  • Unquoted strings won't work any more. For example, $array[key] was considered something like a »half-valid« syntax for a long time. PHP would check if there is a constant with the name key, and if it can't find one, use "key" as a string. This is discouraged and prints a warning for a long time now, and will finally be a hard error in PHP 8. So if you developed with all error reporting enabled, you are already safe. If not, better change your dev environment.
  • You can't have old-style # comments any more that start with #[. That's the attribute syntax now. Solution: Replace with // or insert a space.
  • each() is gone. Damn.
  • create_function() is gone. Good.
  • Support for __autoload() is removed. This probably isn't in any code you use since we got spl_autoload_register() with PHP 5.1, but better check.

There are many, many more breaking changes. But I would classify them more as bugfixes than anything else, i.e. I really hope you never had code that relied on any of this, or got rid of it a long time ago. For example, parse_str() was able to import variables in the global scope. This is not possible any more, but should not have been used anyway.

There are also many, many new features I'm excited to get my hands on. But this is for another post.

Kommentare zu diesem Beitrag können per E-Mail an den Autor gesandt werden.

[ ← Zurück zur Übersicht ]

Impressum & Datenschutz