PHP ternary operator gives unexpected result

Asked

Viewed 508 times

3

Recently I did a test and there was a question asking what the return of expression:

$var = true ? '1' : false ? '2' : '3'

I replied that the result would be '1', but the correct result is '2'. If the code is written:

$var = true ? '1' : (false ? '2' : '3')

It will return '1'.

Why?

1 answer

7


This is a problem of associativity, and "by table", of precedence. Every well thought-out and well-made language has this operator with right-to-left associativity. This makes much more sense in this type of operator, but PHP obviously chose the wrong path, like so many other things, and uses the associativity from left to right. Join the fact that it’s a weak typing language and interpreting a guy as if it were another, it’s a mess. remembering that the complete operator who is the leftmost is a single operation:

(true ? '1' : false) ? '2' : '3'

What is the result of the expression in parentheses (obviously the first one to be executed? If it is true it is clear that the result is '1'. So far easy. Now that we know this result we will rewrite the expression with the result:

'1' ? '2' : '3'

'1' is true or false? According to documentation it is considered true by PHP, whatever value it is false, 0, 0.0, "0", array or SimpleXML (do not ask me because only has this exception) of zero elements, or NULL, is false, the rest is true.

Therefore being true the result is '2'.

The second you are changing precedence with explicit parentheses, presumably where you want. The first expression is isolated and the condition already being true already falls in the first operand after the condition, the false operand is never executed in this case, it neither evaluates the expression that is in parentheses.

Anyway in any programming language one should avoid nesting conditional operators (do not call them ternaries because one day may have another ternary that is not that conditional, being ternary is another level of classification than it is). If nesting, prefer to be more readable by placing explicit parentheses on what you want. This applies to any operator that does not have such obvious precedence (that is, all those that are not arithmetic, and probably relational are also very quiet, for those who are experienced can take a chance on logics).

echo true ? '1' : false ? '2' : '3';
echo "\n";
echo true ? '1' : (false ? '2' : '3');

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.