I just started upgrading my code to be compatible with php 8.1. I have a lot of code snippets where I'm passing potential null values to inner functions.
if (strlen($row) > 0) { ... }
where $row comes from a source (such as a query) that may have null values. This may generate a deprecation warning; in this case:
DEPRECATED: strlen(): Passing null to a parameter of type string is deprecated #1 ($string)
I'm looking for the easiest, most time-efficient way to handle upgrading this code, such as fixing where global search and replace can be done. It seems to typecast the variable I pass to the inner function without changing the functionality.
error_reporting(E_ALL); $row = null; if (strlen((string) $row) > 0) { ... }
Are there any issues with this internal functionality approach, aside from the moral aspects of encoding it this way? Is there a better way (other than completely rewriting the code and handling null values differently)? I prefer this solution to be backwards compatible with v7.4, although I'd probably be 8.0 compatible.
I know there are other options for my user defined function.
Answer to your question about "The easiest, most time-efficient way to handle upgrading this code."
In short, you can't.
First, some background...
About15% of developers use
strict_types=1
, so you are among the majority who don't.You canignore this issue now (deprecated), but PHP 9.0 will cause a lot of problems by making it a fatal type error.
That said, you can still use NULL connection strings: You can still compare NULL to the empty string: And you can still use NULL for calculations (it's still treated as 0): You can still print/echo NULL: You can still pass NULL intosprintf()
You can still force other values (follow rules) like NULL coercion has worked this way since then, I assume from the beginning, and that's documented too:and force it to an empty string using
%s, e.g.
Anyway, to fix...
The firstpart, it will try to find the code you need to update.
This occurs whenever NULLcan be passed to one of these function arguments.
There are at least335parametersaffected by this.
There is also an extra104, they are a bit fishy; and558 where NULL has problems, where should you fix these, e.g.define(NULL, 'value')
.
Psalmis the only tool I can find that helps with this.
Psalms need to be at a very high inspection level (1, 2 or 3). And you can't use baselines to ignore problems (techniques where developers introduce static analysis in existing projects, so it only checks new/edited code). If you haven't used a static analysis tool before (don't worry, it's only recommended for33% of developers); then expect to spend a lot of time modifying your code (starting at level 8, max. loose, then slowly increase).
I cannot use PHPStan, Rector, PHP CodeSniffer, PHP CS Fixer, or PHPCompatibility to find these issues (source).
After you find each question,The secondpart is editing.
The least likely place to cause a problem is to replace the sink, for example
Alternatively, you could try tracing back to the source of the variable and try preventing it from being set to NULL in the first place.
The following are some very common sources of NULL:
Some of these functions require a second parameter to specify a default value, or you can use
strval()
ahead of time...but be careful, your code may pass ($a = == NULL), and you don't want to break it.Many developers don't realize that some of their variables can contain NULL - such as expecting
(that they create) to always submit all input fields; due to network issues, browser extensions, users Editing the DOM/URL etc. in the browser, this may not happen.I have been working on this problem for most of the year.
I started writing two RFCs to try to solve this problem. The first is to update some functions to accept NULL (which is not ideal, as it upsets developers who use strict_types);The second RFCis to allow NULL to continue to be enforced in this case. .....but I didn't put it up for a vote because I just received a ton of negative feedback and I didn't want that rejection referenced in the future to explain why this issue couldn't be fixed (andthe initial changes were barely Discussion, this one).
It seems that NULL is handled differently because it is never treated as a "scalar value" - I don't think many developers care about this distinction, but it comes up from time to time.
Most of the developers I've worked with ignore this issue (hoping to fix it later, which is probably not the best idea); e.g.
There is a team trying to apply
strval()
to everything, likeprune(strval($search))
. But more than a year later they're still seeing issues (they said they were testing with 8.1 alpha 1).Another option I'm considering is to create a library that redefines all these ~335 functions as nullable under a namespace; e.g.
The developer will then include the library and use the namespace themselves:
If you are explicitly trying to handle the
null
case, a slightly cleaner fix is tostrlen($row ?? '')
use the "null coalescing operator".In most cases the two are probably equivalent, but with
strict_types=1
in effect they will behave differently if the value is of another type that can be converted to a string Difference:On the other hand, note that the
??
operator is based onisset
, not=== null
, sois undefinedVariables behave differently:If you care about this case, the most direct equivalent to the old behavior is more verbose: