Nested shorthand if bug [duplicate] - php

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.

Related

PHP Ternary Operators don't work as expected? [duplicate]

This question already has answers here:
Stacking Multiple Ternary Operators in PHP
(11 answers)
Closed 4 years ago.
I have a method that I'm checking if param is null, but if I use a ternary operator to make sure the false result isn't a string, I don't get the same expected result... I am a full stack .NET dev by day, but do some PHP free lance and this just stumped me...
$param = null;
// $active evaluates to true
$active = is_null($param) ? true : false;
// $active evaluates to false
$active = is_null($param) ? true : is_string($param)
? (strtolower($param) === 'true')
: true;
I have used nested ternary operators in C# and JavaScript what feels like countless times, but I don't know if I have ever tried in PHP... does PHP attempt to evaluate all nested ternary operations prior to expressing a result or is there something I'm missing here since from my understanding in this case, the ternary operator should be short circuited and evaluated to true in both circumstances.
The ternary operator is left associative unlike most other languages such as C#. The code:
$active = is_null($param)
? true
: is_string($param)
? (strtolower($param) === 'true')
: true;
is evaluated as follows:
$active = ((is_null($param) ? true : is_string($param))
? (strtolower($param) === 'true') : true);
You must explicitly add parenthesis to make sure ?: works the way it does in familiar languages:
$active = is_null($param)
? true
: (is_string($param)
? (strtolower($param) === 'true')
: true);
You need to wrap your second ternary condition with parenthesis (),
<?php
$param = null;
// $active evaluates to true
$active = is_null($param) ? true : false;
echo "Simple ternary result = $active".PHP_EOL;
// $active evaluates to true
$active = is_null($param) ? true : (is_string($param)? (strtolower($param) === 'true'): true);
echo "Nested ternary result = $active";
?>
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:
See Example #4 here at http://php.net/manual/en/language.operators.comparison.php
Example #4 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.
?>
DEMO: https://3v4l.org/gW8pk
This is a well-known problem with PHP. I doubt it will ever be fixed. Use parentheses, or if..else or switch statements, to get the behaviour you want.
(In technical terms, the ternary operator in PHP is "left associative", while that in every other language with this operator is "right associative". The latter is the more logical behaviour for this operator.)

Ternary Operator shows 1 instead on null

Hello I am using ternary operator to show links in case if they exist, in case if the database field is NULL I don't want to show anything. Right now it is showing 1. how I can escape this ?
echo "".(($row['photo_01']=='')? :'<li><img src="uploads/'.$row['photo_01'].'"></li>')."
If you leave the second part of the ternary operator empty, it is equivalent to this:
echo "".(($row['photo_01']=='')
? ($row['photo_01']=='') // this is duplicated
:'<li><img src="uploads/'.$row['photo_01'].'"></li>')."
More generalized:
($x ? $x : $y) === ($x ?: $y)
($row['photo_01']=='') is evaluated to be true, which is echoed out as 1, so you need to update your code to be like this:
echo "".(($row['photo_01']=='')? '' :'<li><img src="uploads/'.$row['photo_01'].'"></li>')."
Of course you could always clean it up like this:
echo "".($row['photo_01'] ? '<li><img src="uploads/'.$row['photo_01'].'"></li>' : '')."
Use empty quotes to represent null ' ', as well as put the result of the ternary in a variable then use it in the echo to prevent cofusion:
$result = ($row['photo_01']=='') ? '' :'<li><img src="uploads/'.$row['photo_01'].'"></li>';
echo $result;

What does the greater than symbol do on the left side of a ternary operator in PHP?

I came across a new syntax for a ternary operation in PHP.
$this->view->totalNumber > $itemsPerPage ? $this->view->renderPaginator = true
: $this->view->renderPaginator = false;
Is this some sort of short-hand for only apply the ternary operation if the resulting value is greater than the existing value for the left side variable?
It's just the comparison operation. You can rewrite it like this if it helps you understand:
($this->view->totalNumber > $itemsPerPage) ? $this->view->renderPaginator = true : $this->view->renderPaginator = false;
Now a better way to write it would be simply to do:
$this->view->renderPaginator = ($this->view->totalNumber > $itemsPerPage);
$this->view->renderPaginator = $this->view->totalNumber > $itemsPerPage;
Really , people. You all should be ashamed.
It looks like all that code is doing is evaluating the expression
$this->view->totalNumber > $itemsPerPage
which resolves to a boolean true or false, which is then checked by the ternary operator.
Enclosing it in parentheses would make it more clear:
($this->view->totalNumber > $itemsPerPage) ? $this->view->renderPaginator = true : $this->view->renderPaginator = false;
This is a shorthand if statement. A more complex version of
($a > $b) ? "execute here if a is greater than b" : "here if not";
So the greater than symbol™ works just as a comparison operator.

What does "isset($x) ? $y : $z" mean? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the PHP operators "?" and ":" called and what do they do?
Reference - What does this symbol mean in PHP?
I know what isset means in PHP. But I have seen syntax like isset($x) ? $y : $z. What does it mean?
That is a Ternary Operator, also called the "conditional expression operator" (thanks Oli Charlesworth). Your code reads like:
if $x is set, use $y, if not use $z
In PHP, and many other languages, you can assign a value based on a condition in a 1 line statement.
$variable = expression ? "the expression was true" : "the expression was false".
This is equivalent to
if(expression){
$variable="the expression is true";
}else{
$variable="the expression is false";
}
You can also nest these
$x = (expression1) ?
(expression2) ? "expression 1 and expression 2 are true" : "expression 1 is true but expression 2 is not" :
(expression2) ? "expression 2 is true, but expression 1 is not" : "both expression 1 and expression 2 are false.";
That statement won't do anything as written.
On the other hand something like
$w = isset($x) ? $y : $z;
is more meaningful. If $x satisfies isset(), $w is assigned $y's value. Otherwise, $w is assigned $z's value.
It's shorthand for a single expression if/else block.
$v = isset($x) ? $y : $z;
// equivalent to
if (isset($x)) {
$v = $y;
} else {
$v = $z;
}
It means if $x variable is not set , then value of $y is assigned to $x , else value of $z is assigned to $x.

PHP 5.3.3 puzzle, what it prints and why

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.
?>

Categories