-
Notifications
You must be signed in to change notification settings - Fork 88
Plugin and theme migration guide to PHP 8
For developers targeting PHP 8 with their themes and plugins.
Old Serendipity code clashed with PHP 8 because of a couple common issues, many of those are also to be found in themes and plugins. To avoid and fix those and be compatible with PHP 8, follow these steps:
If serendipity['production']
is true
, Serendipity's error handler will suppress all non-fatal errors and warnings. If your goal is to produce good code, set it to false in your serendipity_config.inc.php and fix all warnings. If you just want your code to work, set it to true. Test your plugin. If the code fails with a 500 error page, set it back to false and check the last error message - it will be a fatal error that has to be fixed.
Alpha versions will by default set serendipity['production']
to false
. Beta, RC and stable versions set it to true. You can overwrite it manually in serendipity_config.inc.php.
Note that code that goes into the core is not allowed to produce any complaints by PHP. If you want your code to be bundled with serendipity, set serendipity['production']
to false
while developing.
Silencing errors with @
does not work in PHP 8 anymore. Errors will still be reported and can still block the code execution. Do not use @
, fix the error instead. @
s that are still in the code can be ignored or removed, though sometimes they can be a nice hint at the developer's intention.
Do not access variables that are not already defined. We did that a lot:
if ($serendipity['GET']['something'] == 'abc') {
$x = true;
}
if ($x) { # Error! x can be undefined
do_something();
}
Initialize x with a default value instead.
Note: This can be ignored for now if serendipity['production'] == true
.
The code in the example above can also fail earlier:
if ($serendipity['GET']['something'] == 'abc') { # This will fail if $serendipity['GET']['something'] was not set
$x = true;
}
We need for check for its existence instead:
if (isset($serendipity['GET']['something']) &&
is_array($serendipity['GET']) &&
$serendipity['GET']['something'] == 'abc') {
$x = true;
}
??
can sometimes be used instead:
if (($serendipity['GET']['something'] ?? '') == 'abc') {
$x = true;
}
Note: This can be ignored for now if serendipity['production'] == true
.
Accessing a constant that does not exist will produce a fatal error. Only access already defined constants.
Similarly, redefining constants will produce a fatal error. This happened a lot in themes and plugins with the old default code to load language constants:
$probelang = dirname(__FILE__) . '/' . $serendipity['charset'] . 'lang_' . $serendipity['lang'] . '.inc.php';
if (file_exists($probelang)) {
include $probelang;
}
include dirname(__FILE__) . '/lang_en.inc.php'; # Error: This will redefine constants when using other languages
Use this instead:
@serendipity_plugin_api::load_language(dirname(__FILE__));
load_language
disables the error reporting when reading a language constant file and thus avoids this problem.
Some old PHP constructs are invalid now. For example each, which was almost exclusively used for while-list-each:
while (list($key, $val) = each($fruit)) {
echo "$key => $val\n";
}
Use foreach
instead.
Very often, smarty templates did something like this:
{if $error_message}
<div class="error">$error_message</div>
{/if}
And the PHP code calling this template only set $error_message
if there was an error.
As Smarty so far does nothing to prevent it, this will produce a warning with PHP 8. The compiled PHP code tries to access an undefined array key. Future Smarty releases could fix this, but that did not happen yet, so you have to fix it on our side instead.
Either:
- Define
$error_message
in the PHP code also if there is no error, and set it to false. - Check that the variable is defined:
{if isset($error_message) AND $error_message}
Note: This can be ignored for now if serendipity['production'] == true
.