On Fri, 3 Jan 2025 at 16:03, Kamil Tekiela <tekiela...@gmail.com> wrote:
> It is a step towards making the user-defined functions and built-in > functions consistent with each other. > Just to note, it could have been "consistent" if NULL coercion was supported for user-defined functions (when not using strict types), in the same way that user defined functions coerce the other types: function example(string $s, int $i) { var_dump($s); var_dump($i); } example("123", "321"); example(123, 321); example(1.23, 3.21); // Deprecated, 3.21 loses precision to 3 (which is fair) example(true, false); example(NULL, NULL); // Will be a fatal error in PHP 9? Fortunately NULL coercion does still work in other contexts: $nullable = NULL; if ('' == $nullable) {} print($nullable); echo $nullable; sprintf('%s', $nullable); var_dump('ConCat ' . $nullable); var_dump(3 + '5' + $nullable); var_dump($nullable / 6); And, NULL coercion is documented: https://www.php.net/manual/en/language.types.string.php “null is always converted to an empty string” https://www.php.net/manual/en/language.types.integer.php “null is always converted to zero (0)” https://www.php.net/manual/en/language.types.float.php “For values of other types, the conversion is performed by converting the value to int first and then to float” https://www.php.net/manual/en/language.types.boolean.php “When converting to bool, the following values are considered false [...] the unit type NULL” --- > You say that $fieldValue in your code can be either a string or null, but > you don't explain why it can be null. When working with web pages (think GET/POST/COOKIE values), or databases, NULL is common: $search = ($_GET['q'] ?? NULL); // Common since PHP 7 $search = (isset($_GET['q']) ? $_GET['q'] : NULL); $search = filter_input(INPUT_GET, 'q'); $search = $request->input('q'); // Laravel $search = $request->get('q'); // Symfony $search = $this->request->getQuery('q'); // CakePHP $search = $request->getGet('q'); // CodeIgniter --- > Using ?? '’ is a cheap solution to avoid the deprecation message, but it's > not a good solution. An alternative is to use `(string) $var`, which some may argue is more dangerous than using coercion :-) This is how Rector deals with the issue; the NullToStrictStringFuncCallArgRector will litter your code with loads of changes, basically anything it can't be sure of the type will be coerced: -echo htmlspecialchars($var) +echo htmlspecialchars((string) $var) And it needs to do this for ~287 functions: https://github.com/rectorphp/rector-src/blob/main/rules/Php81/Enum/NameNullToStrictNullFunctionMap.php There are several projects I have not done this to (because it changes thousands of lines of code). With new code, I've just go into the habit of doing ugly things like `trim(strval($a))`, and for templating I've taken a similar approach to Laravel Blade (abstracting the use of htmlspecialchars): https://github.com/laravel/framework/blob/ab1506091b9f166b312b3990d07b2e21d971f2e6/src/Illuminate/Support/helpers.php#L119 That said, as I expect PHP 9 to trigger a Fatal Error every time this happens (last time I raised this, lets just say it wasn't a pleasant experience), I'm tempted to create a simple library to re-define all of these functions, e.g. namespace FixNullCoercion; function urlencode($string) { return \urlencode($string ?? ''); } function trim($string, $characters = " \n\r\t\v\x00") { return \trim($string ?? '', $characters); } function htmlspecialchars($string, $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, $encoding = null, $double_encode = true) { return \htmlspecialchars($string ?? '', $flags, $encoding, $double_encode); } // ... etc for the ~287 functions. Then anyone can include the library, and simply use the FixNullCoercion namespace. In the mean time, as a quick and simple way to ignore the deprecation message, I'm using: function ignore_null_coercion($errno, $errstr) { return ($errno === E_DEPRECATED && preg_match('/Passing null to parameter #.* of type .* is deprecated/', $errstr)); } set_error_handler('ignore_null_coercion', E_DEPRECATED); Craig