Can someone explain the differences between ternary operator shorthand (?:
) and null coalescing operator (??
) in PHP?
When do they behave differently and when in the same way (if that even happens)?
$a ?: $b
VS.
$a ?? $b
Can someone explain the differences between ternary operator shorthand (?:
) and null coalescing operator (??
) in PHP?
When do they behave differently and when in the same way (if that even happens)?
$a ?: $b
VS.
$a ?? $b
When your first argument is null, they're basically the same except that the null coalescing won't output an
E_NOTICE
when you have an undefined variable. The PHP 7.0 migration docs has this to say:Here's some example code to demonstrate this:
And it's output:
The lines that have the notice are the ones where I'm using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.
Execute the code: https://3v4l.org/McavC
Of course, this is always assuming the first argument is
null
. Once it's no longer null, then you end up with differences in that the??
operator would always return the first argument while the?:
shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.So:
would then have
$a
be equal tofalse
and$b
equal to'g'
.Ran the below on php interactive mode (
php -a
on terminal). The comment on each line shows the result.So this is my interpretation:
1. The Null Coalescing Operator -
??
:??
is like a "gate" that only lets NULL through.NULL
.??
is same as( !isset() || is_null() )
2. The Ternary Operator -
?:
?:
is like a gate that letsanything falsy
through - includingNULL
0
,empty string
,NULL
,false
,!isset()
,empty()
.. anything that smells falsyecho ($x ? $x : false)
?:
will throwPHP NOTICE
on undefined (unset
or!isset()
) variables3. So doctor, when do I use
??
and?:
..?:
whenempty($x)
checks!empty($x) ? $x : $y
can be shortened to$x ?: $y
if(!$x) { fn($x); } else { fn($y); }
can be shortened tofn(($x ?: $y))
??
when!isset() || is_null()
check$object = $object ?? new objClassName();
4. Stacking operators ...
Ternary Operator can be stacked ...
Source & credit for this code
This is basically a sequence of:
Null Coalese Operator can be stacked ...
This is a sequence of:
Using stacking, I can shorten this:
To this:
Cool, right? :-)
It seems there are pros and cons to using either
??
or?:
. The pro to using?:
is that it evaluates false and null and "" the same. The con is that it reports an E_NOTICE if the preceding argument is null. With??
the pro is that there is no E_NOTICE, but the con is that it does not evaluate false and null the same. In my experience, I have seen people begin using null and false interchangeably but then they eventually resort to modifying their code to be consistent with using either null or false, but not both. An alternative is to create a more elaborate ternary condition:(isset($something) or !$something) ? $something : $something_else
.The following is an example of the difference of using the
??
operator using both null and false:By elaborating on the ternary operator however, we can make a false or empty string "" behave as if it were a null without throwing an e_notice:
Personally, I think it would be really nice if a future rev of PHP included another new operator:
:?
that replaced the above syntax. ie:// $var = $false :? "true";
That syntax would evaluate null, false, and "" equally and not throw an E_NOTICE...Scroll down on this link and view the section, it gives you a comparative example as seen below:
However, it is not advised to chain the operators as it makes it harder to understand the code when reading it later on.
Essentially, using the coalescing operator will make it auto check for null unlike the ternary operator.
If you use the shortcut ternary operator like this, it will cause a notice if
$_GET['username']
is not set:So instead you have to do something like this:
The null coalescing operator is equivalent to the above statement, and will return 'default' if
$_GET['username']
is not set or isnull
:Note that it does not check truthiness. It checks only if it is set and not null.
You can also do this, and the first defined (set and not
null
) value will be returned:Now that is a proper coalescing operator.
The major difference is that
Ternary Operator expression
expr1 ?: expr3
returnsexpr1
ifexpr1
evaluates toTRUE
but on the other hand Null Coalescing Operator expression(expr1) ?? (expr2)
evaluates toexpr1
ifexpr1
is notNULL
Ternary Operator
expr1 ?: expr3
emit a notice if the left-hand side value(expr1)
does not exist but on the other hand Null Coalescing Operator(expr1) ?? (expr2)
In particular, does not emit a notice if the left-hand side value(expr1)
does not exist, just likeisset()
.TernaryOperator is left associative
Null Coalescing Operator is right associative
Now lets explain the difference between by example :
Ternary Operator
(?:)
Null Coalescing Operator
(??)
Here is the table that explain the difference and similarity between
'??'
and?: