PHP - correct ternary implementation [closed] - php

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Ok,
so consider the following:
$this->foo = isset($_GET['foo']) && !empty($_GET['foo']) ? $_GET['foo'] : NULL;
and this:
$this->foo = (isset($_GET['foo']) && !empty($_GET['foo'])) ? $_GET['foo'] : NULL;
When I write an if / else statement with multiple checks, I generally include the extra parenthesis as in the second example. In the ternary, both examples work.
Should I add the extra parenthesis as on the bottom? Or go with the first?
Thanks

Operator precedence is the issue as to when parenthesis are necessary (notwithstanding readability).
When dealing with the ternary operator look at the order PHP uses to group expressions, start with the ternary operator(s) and examine the operators that are grouped after the ternary operator. Those are the operators that have the potential to produce erroneous output.
PHP Operator Precedence, starting with ternary:
Assoc. Operators Additional Information
...
left ? : ternary
right = += -= *= **= /= .= %=
&= %= &= |= ^= <<= >>= => assignment
left and logical
left xor logical
left or logical
left , many uses
In this case there are the assignment operators, the lower precedence logical operators, and comma.
It appears the ternary and assignment are equal, therefore grouping is determined by their associativity when the two are in the same statement.
$a = true? 'yes': 'no';
// $a is assigned 'yes'
Assignment is right associative so, in relation to the =, expressions are grouped right to left. In this case the ternary comes first (rightmost) and the statement works as expected.
That leaves the lower precedence boolean and the comma.
echo true and true? 'yes': 'no';
// Echos: 1
// Grouped like: echo true and (true? 'yes': 'no');
Not as expected. Use parenthesis to force intended grouping:
echo (true and true)? 'yes': 'no';
// Echos: yes
When using higher precedence boolean operators, which are grouped before the ternary operator, parenthesis are not necessary.
echo true && true? 'yes': 'no';
// Echos: yes
Bottom line, when operator precedence is unclear, or readability is desired, use parenthesis.

The PSR-2 standard specifically omits any opinion on operators. But in this case, i'll go with the simple one:
$this->foo = isset($_GET['foo']) && !empty($_GET['foo']) ? $_GET['foo'] : NULL;

I am for the first approach:
$this->foo = isset($_GET['foo']) && !empty($_GET['foo']) ? $_GET['foo'] : NULL;
simplified to
$this->foo = !empty($_GET['foo']) ? $_GET['foo'] : NULL;
empty already check the isset. I would include parathenis in this case only when condition has more then 3 statements. Consider that the 1 line if/else normally is used when the condition is simple, other wise to have a more readable if else you should go with classic if {} else {}

Related

logical vs assignment operator precedence in PHP

Recently i came upon such snippet:
$x = 2 && $y = 3; echo (int)$x.':'.(int)$y;
Which produces output 1:3.
By looking at operator precedence sheet i see that logical operators || and && has higher precedence than assignment operator =. So first expression should be evaluated as $x = (2 && $y) = 3; which becomes $x = (2 && null) = 3; and finally evaluates to $x = false = 3; Secondly - assignment operator has right associativity, so interpreter should try to execute false = 3 which is illegal of course. So in my opinion above mentioned code snippet should not compile at all and must throw parse or run-time error. But instead of that script produces 1:3. Which means that interpreter executed actions are:
a) $y=3
b) 2 && $y
c) $x = (2 && $y)
Why it is so and not according to operator precedence ?
The operator precedence sheet you link to states as a separate note:
Although = has a lower precedence than most other operators, PHP will
still allow expressions similar to the following: if (!$a = foo()), in
which case the return value of foo() is put into $a.
So, in effect, an assignment inside an expression will be treated somewhat like a sub-expression. Exactly how and when this will happen isn't clear from the documentation, which just states that "similar" expressions will work this way.

PHP can't take more than one ternary operator?

Basically I have the following code:
However when I var_dump $isLoggedIn and $isset($_COOKIE['access_token']) both are false (so through the ! in the <?php?> it gets true) and the href should be connect.php... but it always is main.php?auto=true".autoooooo does not even exist (I just made it for testing) and href should actually be empty.
What am I doing wrong?
In php, the ternary operator (?:) associates left-to-right (unlike in C or perl where it associates right-to-left).
That means that it evaluates the first test ? value 1 : value 2, and then uses that result to determine which value of the second operator to use.
Your construct would work in C or perl, but in php, you need to add brackets around each subsequent ternary operator.
Also, for readability, I recommend you add quite a few newlines and indents in your code.
Use brackets for your 2nd clause:
$b1 = false;
$b2 = false;
echo $b1 ? 'b1 true' : ($b2 ? 'b2 true' : 'all false') ;
Output:
all false

how ordering makes a difference within an expression for an if statement

I have an array ...
$a= array(1,2,3,4);
if (expr)
{ echo "if";
}
else
{ echo 'else';
}
When expr is ( $a = '' || $a == 'false') , output is "if" ,
but when expr is ( $a == 'false' || $a = '' ) , output is "else"
Can anyone explain why & how ordering makes a difference ??
Edit : I understand that I am assigning '' to $a. That is not the problem. The real question is : What does the expression $a = '' return? And why does reversing the order of the 2 situations switch us from the IF section to the ELSE section?
AGAIN : I UNDERSTAND I AM ASSIGNING NOT COMPARING. PLEASE ANSWER THE QUESTION AS IS.
First, never use = as a comparison operator. It is an assignment operator.
The difference is that false (as a boolean) is not the same as 'false' as a string.
Certain expressions are type juggled by PHP to evaluate somewhat differently to how you would expect.
false==""
// TRUE.
false=="false"
// FALSE.
Additionally, when you try to compare numbers to strings, PHP will try to juggle the data so that a comparison will be performed. There is a lot to it (much more than I will post here) but you would do well to investigate type juggling and various operators. The docs are a great start for this. You should also have a read of the comparison operators which go into a lot of detail about how various comparisons will work (depending on whether you use == or === for example).
With $a = '' you are setting $a to an empty string. This is the same as:
$a = '';
if($a){
echo 'if';
}
The || operator checks if the first condition is true and if it is, it continues with the code in the brackets. In PHP, if $a is set to anything, it will return true. In the second case $a does not equal the string 'false' (you are not comparing it to a boolean false even!), so it executes the code in the else part.
And Fluffeh is not entirely correct. You can use the assignment operator in an if condition very effectively, you just have to be smart about it.
$a = '' is an assignment: you have, in error, used = in place of ==. Assignment is an expression which has the value of the thing your assigning.
A single equals sign = is the assignment opporator, so $a = '' is assigning an empty string to $a not checking if it is equal to.
In your 1st example you set the value of $a to an empty string, then check if it is false. An empty tring evalutes to false in php, so the conditional is true.
In your second example, you check if $a equals false 1st (when the value of $a is an array), so the conditional is false

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.

Which coding style you use for ternary operator? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I keep it in single line, if it's short. Lately I've been using this style for longer or nested ternary operator expressions. A contrived example:
$value = ( $a == $b )
? 'true value # 1'
: ( $a == $c )
? 'true value # 2'
: 'false value';
Personally which style you use, or find most readable?
Edit: (on when to use ternary-operator)
I usually avoid using more than 2 levels deep ternary operator. I tend prefer 2 levels deep ternary operator over 2 level if-else, when I'm echoing variables in PHP template scripts.
The ternary operator is generally to be avoided, but this form can be quite readable:
result = (foo == bar) ? result1 :
(foo == baz) ? result2 :
(foo == qux) ? result3 :
(foo == quux) ? result4 :
fail_result;
This way, the condition and the result are kept together on the same line, and it's fairly easy to skim down and understand what's going on.
I try not to use a ternary operator to write nested conditions. It defies readability and provides no extra value over using a conditional.
Only if it can fit on a single line, and it's crystal-clear what it means, I use it:
$value = ($a < 0) ? 'minus' : 'plus';
a style I sometimes use, which I'm bringing up since it hasn't been mentioned, is like this:
$result = ($x == y)
? "foo"
: "bar";
..but usually only if putting it all on one line makes it too long. I find that having the = ? : all line up makes it look neater.
Personally, I only use the ternary operator if it fits on one line. If it need to span, then it's time for the good old
if else if else
PHP nested ternary operators behave differently.
This syntax passes all the following tests.
Based on http://deadlytechnology.com/web-development-tips/php-ternary-syntax/
$myvar = ($x == $y)
?(($x == $z)?'both':'foo')
:(($x == $z)?'bar':'none');
.
See: http://au.php.net/ternary
Example #3 "Non-obvious Ternary Behaviour" explains why the following does not work in PHP.
$x = 1;
$y = 2;
$z = 3;
$myvar = ($x == $y)
? "foo"
: ($x == $z)
? "bar"
: "none";
$myvar == 'none'; // Good
$x = 1;
$y = 2;
$z = 1;
$myvar = ($x == $y) ? "foo" : ($x == $z) ? "bar" : "none";
$myvar == 'bar'; // Good
$x = 1;
$y = 1;
$z = 3;
$myvar = ($x == $y) ? "foo" : ($x == $z) ? "bar" : "none";
$myvar == 'bar'; // Bad!
$x = 1;
$y = 1;
$z = 1;
$myvar = ($x == $y) ? "foo" : ($x == $z) ? "bar" : "none";
$myvar == 'bar'; // Bad!
ternary operators are short effective ways to write simple if statements. They shouldn't be nested or difficult to read. Remember: You write the software once but is is read 100 times. It should be easier to read than write.
I tend to enclose the condition in parentheses : (a == b) ? 1 : 0
I'll dissent with the common opinion. I'm sort of like Imran with my conditional operator style. If it fits cleanly on one line, I keep it on one line. If it doesn't fit cleanly on one line, I do break it, but I use only a single tab (4 spaces; I have VS set to insert spaces for tabs) for the indent. I don't immediately jump to if-else, because a lot of the time the conditional operator makes more sense contextually. (If it doesn't make sense contextually, however, I simply don't use it.)
Also, I don't nest conditional operators. At that point, I do find it too difficult to read, and it's time to go to the more verbose if-else style.
The ternary conditional can make code cleaner and more elegant, and most importantly, help you put emphasis on the right things and avoid repeating yourself. Consider using them, but do not make the code less readable by doing so. In VB.NET:
'before refactoring
If x = 0 Then ' If-Then-Else puts emphasis on flow control
label = "None"
Else
label = Foo.getLabel(x) ' If-Then-Else forces repeat of assignment line
End If
'after refactoring
label = If(x = 0, "None", Foo.getLabel(x)) ' ternary If puts emphasis on assignment
Note that "it is less readable" is not the same thing as "I'm not used to seeing that".
The "contrived example" is how I would indent it, except that I would indent from the left margin, not based on where the ( or whatever is on the line above.
To the ternary detractors - readability is the point. If you don't think it makes for more readable code, don't use it. But I find the contrary to be the case at least some of the time.
I don't use it. It always smelled to me like trying to save space and typing in source code with the expectation that small source == more efficient compiled code.
I don't find it readable at all, but much of that is because I just never use it.
Imran, you have formatted this beautifully. However, the ternary operator does tend to get unreadable as you nest more than two. an if-else block may give you an extra level of comprehensible nesting. Beyond that, use a function or table-driven programming.
$foo = (isset($bar)) ? $bar : 'default';
I personally only use it for an assignment of a variable (in java) for example :
String var = (obj == null) ? "not set" : obj.toString();
and (other example) when using function that doesn't allow null parameter such as :
String val; [...]
int var = (val == null) ? 0 : Integer.parseInt(val);
I tend not to use the ternary operator at all as I find if .. else much more readable.

Categories