views:

200

answers:

7

Hi,

I was asked to perform this operation of ternary operator use:

$test='one';

echo $test == 'one' ? 'one' :  $test == 'two' ? 'two' : 'three';

Which prints two (checked using php).

I am still not sure about the logic for this. Please, can anybody tell me the logic for this.

+1  A: 

PHP'S documentation says:

Note: It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:

Example #3 Non-obvious Ternary Behaviour

<?php
// on first glance, the following appears to output 'true'
echo (true?'true':false?'t':'f');

// however, the actual output of the above is 't'
// this is because ternary expressions are evaluated from left to right

// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');

// here, you can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>

If you put parenthesis around the false statement, it prints one:

echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : 'three');
Felix Kling
A: 

Nested ternary operations are gross! The above explanation shows why.

Basically this is the logic:

is $test == 'one'

  if TRUE then echo 'one'

  else is $test == 'two'

      if TRUE then echo 'two'

      else echo three
John Conde
I think you are on the right track and have the best explanation but your logic doesn't add up yet, as it is not outputting `one`
Pekka
Filix Kling's explanation answers that question although it doesn't make sense why parenthesis are needed.
John Conde
+5  A: 

It works correctly when you use brackets:

<?
 $test='one';
 echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : 'three');

I don't understand it 100% but without brackets, to the interpreter, the statement must look like this:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

the result of the first condition seems to be returned as the result of the whole ternary operation.

Pekka
+1  A: 

I think that it is evaluated like this:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

($test == 'one' ? 'one' : $test == 'two') is non-zero/null, so 'two' is logical output

if you want it to work correctly, write:

echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : 'three');
hamax
+8  A: 

Well, the ? and : have equal precedence, so PHP will parse left to right evaluating each bit in turn:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

First $test == 'one' returns true, so the first parens have value 'one'. Now the second ternary is evaluated like this:

'one' /*returned by first ternary*/ ? 'two' : 'three'

'one' is true (a non-empty string), so 'two' is the final result.

Nicholas Wilson
This is the shortest correct explanation :) +1.
Pekka
rite said Pekka
nik
+1 for brevity and clarity of explanation (a difficult combination)
Mark Baker
+7  A: 

Basically interpreter evaluates this expression from left to right, so:

echo $test == 'one' ? 'one' :  $test == 'two' ? 'two' : 'three';

is interpreted as

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';

And the expression in paratheses evaluates to true, since both 'one' and 'two' are not null/o/other form of false. So if it would look like:

echo $test == 'one' ? FALSE :  $test == 'two' ? 'two' : 'three';

It would print three. To make it work okay, you should forget about combining ternary operators, and use regular ifs/switch for more complicated logic, or at least use the brackets, for the interpreter to understand your logic, and not perform checking in standard LTR way:

echo $test == 'one' ? 'one' :  ($test == 'two' ? 'two' : ($test == 'three' ? 'three' : 'four'));

//etc... It's not the most understandable code... 

//You better use:
if($test == 'one')
    echo 'one';
else { //or elseif()
...
}

//Or:
switch($test) {
    case 'one':
        echo 'one';
        break;
    case 'two':
        echo 'two';
        break;
//and so on...
}
raceCh-
Exactly, I was about to post it, I found it in the php documentation. :)
M28
+1  A: 

Ternary operators are executed in order of appearance so you really have:

echo ($test == 'one' ? 'one' :  $test == 'two') ? 'two' : 'three';
Kamil Szot