Migration to PHP 8.1 - how to fix Deprecated Passing null to parameter error - rename build in functions

Viewed 19360

PHP 8.1 has deprecated passing null as parameter to a lot of functions. The main problem is with functions like "htmlspecialchars" and "trim", where null no longer is silently converted to empty string. To fix this issue with out going thru huge amount of code I was traying to rename original build in functions and replace them with wrappers that can fix input from null to empty string. The main problem is, that function "rename_function" no longer works, last update on this is from 2004. I need some sort of override of build in functions, to avoid writing null check each time function is called making all my code x2 larger. Only other solution I can think of is to use only my custom functions, but this still require going thru all my code un and third party libraries I have.

In PHP 8.1 when null is passed to build in function, it is no longer silently converted to empty string.

4 Answers

Firstly, two things to bear in mind:

  1. PHP 8.1 deprecates these calls, it does not make them errors. The purpose of deprecation is to give authors advance notice to fix their code, so you and the authors of libraries you use have until PHP 9.0 comes out to fix things. So, don't panic that not everything is fixed right away, and be patient with library maintainers, who will get to this in their own time.
  2. The quick fix in most cases is to use the null coalescing operator to provide a default value as appropriate, so you don't need a long null check around every use. For instance, htmlspecialchars($something) can be replaced with htmlspecialchars($something ?? '')

Next, some options:

  • Depending how many cases you have, you may be able to just fix them manually a few at a time, either adding ?? '' or fixing a logic bug where you weren't expecting a null anyway.
  • Create custom functions like nullable_htmlspecialchars and do a straight-forward find and replace in your code.
  • Create custom namespaced functions like nullableoverride\htmlspecialchars; then in any file where you add use function nullableoverride\htmlspecialchars; that function will be used instead of the built-in one. This has to be added in each file, though, so you may need a tool to automate adding it.
  • Use Rector to automate adding ?? '' to appropriate function calls, so you don't have to edit them all by hand. Unfortunately, there doesn't seem to be a built-in rule for this (yet), so you'd have to learn to write your own.
  • Possibly simpler, depending on your skills, use a regular expression find-and-replace to add the ?? '' to simple cases.

A solution for existing projects with a lot of pages, that you want to migrate to PHP8+:

In my case, most problems came with "trim" function that receives null values. In that case, you can create a custom "trim" function and then replace in your existing code the "trim" for "custom_trim" function:

public function custom_trim(?string $value)
{
    return trim($value ?? '') ;
} 

while waiting to correct the problems (there may be many) it is possible to define a custom error handling function to ignore them.

For exemple :

error_reporting(E_ALL) ;
set_error_handler(
    function($severity, $message, $file, $line) {
        if ( !$severity || error_reporting()!=E_ALL ) return ;  // to treat @ before functions
        $erreurs_autorisees = array(
            E_NOTICE          => "Notice",
            E_USER_NOTICE     => "User Notice",
            E_DEPRECATED      => "Deprecated",
            E_USER_DEPRECATED => "User Deprecated",
            E_WARNING         => "Warning",
            E_USER_WARNING    => "User Warning",
        ) ;
        if ( isset($erreurs_autorisees[$severity]) ) {
            $warning_autorises = [
                "addslashes(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "base64_decode(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "htmlspecialchars(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "mb_decode_mimeheader(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "mysqli_real_escape_string(): Passing null to parameter #2 (\$string) of type string is deprecated",
                "preg_replace(): Passing null to parameter #3 (\$subject) of type array|string is deprecated",
                "preg_split(): Passing null to parameter #3 (\$limit) of type int is deprecated",
                "rawurlencode(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "setcookie(): Passing null to parameter #2 (\$value) of type string is deprecated",
                "str_starts_with(): Passing null to parameter #1 (\$haystack) of type string is deprecated",
                "strcmp(): Passing null to parameter #1 (\$string1) of type string is deprecated",
                "strlen(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "strtr(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "strpos(): Passing null to parameter #1 (\$haystack) of type string is deprecated",
                "substr(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "trim(): Passing null to parameter #1 (\$string) of type string is deprecated",
                "strncasecmp(): Passing null to parameter #1 (\$string1) of type string is deprecated",
            ] ;
            if ( in_array($message, $warning_autorises) ) return true ;
            
            // On ne converti pas les warning en Exception, on se contente de les logger / les afficher
            $msg = $erreurs_autorisees[$severity].": $message in $file on line $line" ;
            if ( ini_get('display_errors') ) echo $msg ;
            // @error_log($msg) ;  // if you want to log
        }
        else throw new ErrorException($message, 0, $severity, $file, $line) ;
        return true;
    }
);

Well, this deprecated thingy can occur and when trying to return data from empty (NULL) database columns ¯\_(ツ)_/¯

For example this code where $lob is a picture saved as SQLite LOB datatype:

$finfo    = new finfo(FILEINFO_MIME);
$mimeType = $finfo->buffer($lob);
Related