PHP 5.3.3 puzzle, what it prints and why - php

Why it doesn't print what is suppose to print?
<?php
$place = 1;
echo $place === 1 ? 'a' : $place === 2 ? 'b' : 'c';
?>

The manual is your friend. Quote:
<?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.
You are basically doing:
echo ($place === 1 ? 'a' : $place === 2) ? 'b' : 'c';
// which is
echo 'a' ? 'b' : 'c';
// which is
echo 'b';

echo ($place === 1 ? 'a' : $place === 2) ? 'b' : 'c';
echo ('a') ? 'b' : 'c';
echo (true) ? 'b' : 'c';
echo 'b';
Thats why.

The conditional operator evaluates from left to right, so you should write
echo ($place === 1 ? 'a' : $place === 2) ? 'b' : 'c';
echo (true ? 'a' : $place === 2) ? 'b' : 'c';
echo 'a' ? 'b' : 'c';
echo true ? 'b' : 'c'; // outputs b
to clarify. This behavior is well-documented.

What do you think it is supposed to print and why, and what is being printed?
Also, from the PHP manual on ternary expressions:
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:
<?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.
?>

Related

Nested shorthand if bug [duplicate]

Why is this printing 2?
echo true ? 1 : true ? 2 : 3;
With my understanding, it should print 1.
Why is it not working as expected?
Because what you've written is the same as:
echo (true ? 1 : true) ? 2 : 3;
and as you know 1 is evaluated to true.
What you expect is:
echo (true) ? 1 : (true ? 2 : 3);
So always use braces to avoid such confusions.
As was already written, ternary expressions are left associative in PHP. This means that at first will be executed the first one from the left, then the second and so on.
Separate second ternary clause with parentheses.
echo true ? 1 : (true ? 2 : 3);
Use parentheses when in doubt.
The ternary operator in PHP is left-associative in contrast to other languages and does not work as expected.
from the docs
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.
?>
In your case, you should consider the priority of executing statements.
Use following code:
echo true ? 1 : (true ? 2 : 3);
For example,
$a = 2;
$b = 1;
$c = 0;
$result1 = $a ** $b * $c;
// is not equal
$result2 = $a ** ($b * $c);
Are you have used parentheses in expressions in mathematics? - Then, that the result, depending on the execution priority, is not the same. In your case, ternary operators are written without priorities. Let the interpreter understand in what order to perform operations using parentheses.
Late, but a nice example for being carefull from now:
$x = 99;
print ($x === 1) ? 1
: ($x === 2) ? 2
: ($x === 3) ? 3
: ($x === 4) ? 4
: ($x === 5) ? 5
: ($x === 99) ? 'found'
: ($x === 6) ? 6
: 'not found';
// prints out: 6
Result of PHP 7.3.1 (Windows Commandline). I can not understand, why they changed it, because the code becomes really unreadable, if I try to change this.

If else with Ternary operator

Below is the example:
If I write like:
<?php
$var = 'A';
echo ($var == 'B' || $var == 'C') ? 'B or C' : 'A';
?>
//Out will be "A"
But if I write like below:
<?php
$var = 'A';
echo ($var == ('B' || 'C')) ? 'B or C' : 'A';
?>
It give me out put as "B or C".
Here ($var == ('B' || 'C')) is not correct or i am missing something?
Created PHP fiddle: http://phpfiddle.org/main/code/wju-46r
This has no relation to ternary operator. It's about type juggling and comparison.
In second case, you're doing 'B' || 'C' which will be treated as true - since || is logical operator. So 'A' == true is true because of type juggling, thus B or C will be your result
echo ($var === ('B' || 'C')) ? 'B or C' : 'A';
This is the right answer you must have to check data type also.

Why is the output of `echo true ? 'a' : true ? 'b' : 'c';` 'b'? [duplicate]

This question already has answers here:
Using nested ternary operators [duplicate]
(7 answers)
Closed 10 years ago.
I have this bit of PHP code:
echo true ? 'a' : true ? 'b' : 'c';
The output of this is:
b
But the output I expected was:
a
the ternary operator in php is left-associative.
You need to use
echo true ? 'a' : (true ? 'b' : 'c');
Because your code evaluates like this:
echo (true ? 'a' : true) ? 'b' : 'c';
it equivalent to:
echo (true) ? 'b' : 'c';
Then the result is 'b'

unusual ternary operation

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.
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.
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...
}
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.
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');
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');
Ternary operators are executed in order of appearance so you really have:
echo ($test == 'one' ? 'one' : $test == 'two') ? 'two' : 'three';
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

PHP nested conditional operator bug?

return
true ? 'a' :
false ? 'b' :
'c';
This should return 'a', but it doesn't. It returns 'b' instead. Is there a bug in PHP's order of handling the different parts of the conditional operators?
I got the idea from Are multiple conditional operators in this situation a good idea? where it does seem to work correctly.
(the true and false are for the purpose of the example, of course. in the real code they are statements that evaluate to true and false respectively. yes, i know that for sure)
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
From the PHP Manual under "Non-obvious Ternary Behaviour".
Ternary operators are evaluated left to right, so unless you add it the braces it doesn't behave as you expect. The following would work though,
return (true ? "a" : (false ? "b" : "c"));
Suspect it's evaluating (true ? 'a' : false) as the input to the second ternary operator and interpreting 'a' as true. Try bracketing appropriately.
order of operations:
>>> return true ? 'a' : false ? 'b': 'c';
'b'
>>> return true ? 'a' : (false ? 'b': 'c');
'a'
Let me explain in same way it was explained to me. But you have to pay attention in parenthesis to understand what is happening.
The PHP
The PHP code below
true ? "a" : false ? "b" : "c"
Is equivalent to:
(true ? "a" : false) ? "b" : "c"
Another languages
The code below
true ? "a" : false ? "b" : "c"
Is equivalent to:
true ? "a" : (false ? "b" : "c")

Categories