Skip to content
Advertisement

PHP Null Coalesce combined with ternary has unexpected results

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'

Advertisement

Answer

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:

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement