var_dump(3 ?? null);
var_dump(3 ?? null === null);
var_dump(3 === null);
var_dump(3 ?? 1 > 2);
var_dump(null ?? 1 > 2);
What do you consider the outputs to be?
3 # Expected
true # Unexpected: I'd expect false
false # This is also what I'd expect
3 # Wait, what?! Why is it 3 and not true??
false # Oh so it only evaluates the right-side boolean if the left side is null??? How unexpected!
So the question is really this:
Why does the PHP engine value ===
as higher than ??
? In what world would anyone want to compare it like if ($count ?? (null === null))
when that is so counter-intuitive to the desired if (($count ?? null) === null)
?
Given $count = 3; if ($count ?? 1 > 2)
, as a rational person, I would expect this to evaluate to if ((3 ?? 1) > 2) -> if (3 > 2)
and return true
. Instead, it evaluates to if (3 ?? (1 > 2) -> if (3)
, which just happens to be truthy. But I don't think anyone would rationally want this evaluation...
It seems like a bug in the interpreter to me. Is there any good reason for this state of affairs?
You are seeing this result because ??
has lower precedence than any of the comparison operators (see the manual). Thus for example,
$count ?? null === null
evaluates as
$count ?? (null === null)
which evaluates to
$count
as $count
is set.
For most of your tests, that then evaluates to 3
or a
, which are both "truthy", and so the condition test is true. Note that for this particular test, even if $count
was unset, it would still evaluate true as null === null
. So:
$count = 3;
if ($count ?? null === null) { echo "Noooo!!!\n"; } else { echo "Yes!!\n"; }
will output:
Noooo!!!
The one exception is where $count
is set to false
(or any other "falsy" value other than NULL
, such as 0
, ""
or []
), where the result of the evaluation is then false
, which gives you your expected result for
if ($count ?? true === true) { echo "Noooo!!!!\n"; } else { echo "Yes!!\n"; }
If you add parentheses to properly specify your desired operation, everything works as expected e.g.
$count = 3;
if (($count ?? null) === null) { echo "Noooo!!!\n"; } else { echo "Yes!!\n"; }
Output:
Yes!!
Demo showing faulty and corrected code for each example on 3v4l.org