This is tested against PHP 7.4
I'm trying to understand why the first example does not return 'hello' like the other two. Example 3 is the same thing as example 1 except the ternary is encapsulated in parentheses but for some reason the presence of the parentheses on example 3 give the expected result.
Example 2 is the same as example 1 but the ternary syntax is using the shorthand to return back the tested value if it validates and is not encapsulated in parenthesis but the return is as expected.
In my opinion all 3 examples should return 'hello' since the string 'hello' is_set() and !null right? Why is it even looking at the right side of ??
in this case? Left passes, it should be returned. Right? What am I missing here?
var_dump('hello' ?? 'a' ? 'b' : 'c');
// 'b'
var_dump('hello' ?? 'b' ?: 'c');
// 'hello'
var_dump('hello' ?? ('a' ? 'b' : 'c'));
// 'hello'
CodePudding user response:
hello' ?? 'a'
is truthy.
It is evaluated first.
The expression returns hello
which qualifies the printing of b
.
Ideally, developers should avoid combining multiple expressions like this for code clarity.
To avoid ambiguous multi-operator expressions, use sufficient parentheses to make things clear.
echo ('hello' ?? 'a') ? 'b' : 'c';
// which doesn't make sense because the parenthetical will always be truthy
Or
echo 'hello' ?? ('a' ? 'b' : 'c');
To explain the operator precedence page in the PHP manual, the shorthand ternary has a lower precedence/priority than the null coalescing operator. The list of operators is conveniently listed in order of precedence.
Logically, when you have a ternary expression that has an ?
(true) branch and a :
(false) branch, then it doesn't matter what is inside the leading conditional expression -- the returned values MUST be one of the branch values. In this case, the returned value can only ever be b
or c
.
The ?:
(shorthand ternary) allows the conditional evaluation's return value to be returned IF it is truthy, otherwise you get the else (falsey) branch's return value.
See:
- https://www.php.net/manual/en/language.operators.precedence.php
- https://stackoverflow.com/a/69731124/2943403
- PHP Error : Unparenthesized `a ? b : c ? d : e` is deprecated. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`
CodePudding user response:
PHP can have 'Non-obvious Ternary Behaviour' because of how the operator is processed. Using parentheses will make it a lot more obvious what is likely to happen - particularly before PHP 8.
For the first example, it is read as:
('hello' ?? 'a') ? 'b' : 'c'
Since 'hello' is not false
, 'b' is returned.