This question already has answers here:
Reference Guide: What does this symbol mean in PHP? (PHP Syntax)
(24 answers)
Closed 8 years ago.
I am new to Laravel framework(i.e a framework driven from Symfony library) .I was looking at the code of Symfony and came across some short cuts that i think i can use to improve my ability to code neatly.
I want to know about the behavior of these operators? ( ?: etc)
1- $this->history = $history ?: new History();
//Does this mean create object of History class and store in $this->history?
2- $this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects;
3- $this->followRedirects = -1 != $this->maxRedirects;
//Not sure how operators are behaving?i know this is something to do with regex but want to know the logic.
I would appreciate if somebody could post a link of tutorial about regex programming in php like above.
The first and the second use the ternary operator:
condition ? code_if_true : code_if_false
Note that code_if_true or code_if_false can be empty.
the third assigns to the variable the result of the test: -1 != $this->maxRedirects
So, true or false.
1) $this->history = $history ?: new History();
if $history has a value equivalent to false the history attribute is set to a new instance of the class History. If $history has a value equivalent to true, the history attribute is set to the $history value.
2) $this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects;
if $maxRedirects is negative the maxRedirects attribute is set to -1, otherwise it is set to $maxRedirects.
3) $this->followRedirects = -1 != $this->maxRedirects;
if $this->maxRedirects is different from -1, $this->followRedirects is set to true, otherwise false.
The best way to understand it is to look at only one page:
http://php.net/manual/en/language.operators.comparison.php
I think that to work with Symfony you need be more experienced developer. Try to learn PHP first, then you can try to learn how to work with frameworks written on PHP. Also I think that before you will start to learn frameworks you should read some books about Design Patterns.
1) and 3) are known as a ternary. I.e.
echo $isFoo ? "Is foo" : "No foo for you!";
Will echo the "Is foo" if foo is true and "No foo for you!" otherwise.
Since PHP 5.3 you can omit the middle:
echo $fooLabel ?: "Default foo label";
This will show $fooLabel if it is true and "Default foo label" otherwise.
Finally 3)
$this->followRedirects = -1 != $this->maxRedirects;
This simply evaluates -1 != $this->maxRedirects. This will be true if maxRedirects is not equal to -1. The result is then stored in $this->followRedirects.
The if-else shorthand follows the following format:
<condition> ? <condition is met> : <condition is not met>
This:
$age = 20;
echo $age >= 21 ? 'Have a beer' : 'Too young! No beer for you!';
Is the same as this:
if($age >= 21){
echo 'Have a beer';
}else{
echo 'Too Young! No beer for you!';
}
Your example #1, since PHP 5.3, simply omits the first condition of the shorthand and executes new History() only if the condition is not met:
$this->history = $history ?: new History();
Note you can also omit the second condition if you'd like. Also, if the omitted portion of the shorthand is met, 1 is returned, since no other instruction is given.
I thinks it's best to illustrate how these operators work by example:
1)
$this->history = $history ?: new History();
Is equal to
if ($history) {
$this->history = $history;
} else {
$this->history = new History();
}
2)
$this->maxRedirects = $maxRedirects < 0 ? -1 : $maxRedirects;
Is equal to
if ($maxRedirects < 0) {
$this->maxRedirects = -1;
} else {
$this->maxRedirects = $maxRedirects;
}
3)
$this->followRedirects = -1 != $this->maxRedirects;
Is equal to
$this->followRedirects = (-1 != $this->maxRedirects);
Is equal to
if (-1 != $this->maxRedirects) {
$this->followRedirects = true;
} else {
$this->followRedirects = false;
}
Related
I'm a fan if the short if-version, example:
($thisVar == $thatVar ? doThis() : doThat());
I'd like to cut out the else-statement though, example:
($thisVar == $thatVar ? doThis());
However, it wont work. Is there any way to do it that I'm missing out?
You can't use it without the else. But you can try this:
($thisVar != $thatVar ?: doThis());
or
if ($thisVar == $thatVar) doThis();
The ternary operator is designed to yield one of two values. It's an expression, not a statement, and you shouldn't use it as a shorter alternative to if/else.
There is no way to leave out the : part: what value would the expression evaluate to if you did?
If you're calling methods with side effects, use if/else. Don't take short cuts. Readability is more important than saving a few characters.
hmm interesting, because executing the below code is valid. Observe:
for ($i = 1; $i <=10; $i++) {
if ($i % 2) {
echo $i;
}
}
The above code indeed, will output 13579
Notice no 'else' clause was used in the above.
If you wanted to inform the user of whether $i % 2 == FALSE ($i's divisor yielded remainder 0), you could include an else clause to print out the even numbers like shown below:
for ($i = 1; $i <=10; $i++) {
if ($i % 2) {
echo "$i is odd";
echo "<br />";
} else {
echo "$i is even";
echo "<br />";
}
}
Giving you the output:
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even
I hope my amazingly easy to understand examples will help all newcomers to PHP, hands down the 'best' server-side scripting language for building dynamic web applications :-)
USE NULL TO SKIP STATEMENTS WHEN IT IS IN SHORTHAND
$a == $b? $a = 10 : NULL;
Just use logical operators : AND, OR, &&, ||, etc.
($thisVar === $thatVar) && doThis();
a frequent use is :
$obj = doSomething($params) or throw new \Exception('Failed to do');
Working for me:
$leftHand != $rightHand?doThis():null;
$leftHand == $rightHand?null:doThis();
While building a small Feedback-Solution where people can give a number of stars (between 0 and 5), I noticed that all user submitted ratings are stored with just 1 star.
I tried it myself by submitting 5 stars and the backend still shows 1 star.
So I looked into the code and this is the piece that causes the trouble:
$feedback->rating = ($wire->input->post->rating || 1);
Actually the || operator isn't doing what I suspected it to do.
In fact it just returns 1 every time (unless both hand sides are $false).
Check my example code below:
$example1 = ($true || 5);
$example2 = ($false || 5);
$example3 = ($false || $false);
$example4 = (5 || 0);
echo $example1."\n";
echo $example2."\n";
echo $example3."\n";
echo $example4."\n";
Also I made a paste here: https://eval.in/514978.
What I'm assuming is, PHP tries to convert the statements to an integer (either 0 or 1) depending on the given elements, is that true?
I'm used to use the || operator in JavaScript a lot where I can just type
var i = myFunction() || "default";
This will check if myFunction() returns a bool-ish value and if not just uses the right hand side value (rather than turning everything into an int).
|| is the or operator in PHP and it evaluates to either true or false. If you want the binary or operator you should use | instead.
Since everything not equall zero is treated like true it makes sense that all of the evalations give true, which as integer becomes 1.
You can see more info here: http://php.net/manual/en/language.operators.logical.php
Example ----- Name -----Result
$a || $b ------- Or ---------TRUE if either $a or $b is TRUE.
There is a difference to PHP || handling as opposed to other languages.
In PHP 5 || 7 will always return true; the || operator will always return a boolean.
5 || 7 = true;
In other languages like javascript. 5 || 7 will return 5 and 7 || 1 will return 7; the || operator will return the parameter that was evaluated true (or the last parameter);
5 || 7 = 5;
7 || 1 = 7;
0 || 7 || 1 = 7;
0 || 0 = 0;
In PHP you can achieve the same by using a ternary operator:
$result = $int ? $int : 1;
if the $int is implicitly true, $result will be $int, otherwise $result will be 1;
Or since PHP 5.3:
$result = $int ?: 1;
$feedback->rating = ($wire->input->post->rating || 1);
Come on, It is returning TRUE which you see as 1
Try this
echo TRUE; //1
What you are looking for is a ternary operator.
$feedback->rating = $wire->input->post->rating ?: 1;
^^
This gives you that value if it is set, otherwise gives you an actual 1.
I'm still getting used to ternary operators and I find it a helpful way of minimizing code. I can make sense out of it if it is simple like the example showed below (example 1)
Example 1
$OrderType = ($name == 'first' ? 'Fred' : ($name == 'last' ? 'Dabo' : 'RAND()'))
This can be read as: if $name is 'first' then use 'Fred' else if $name is 'last' then use 'Dabo' else use 'RAND()'
However I saw this (example 2) on another website and it doesn't make any sense to me.
Example 2
$score = 10;
$age = 20;
echo 'Taking into account your age and score, you are: ',($age > 10 ? ($score < 80 ? 'behind' : 'above average') : ($score < 50 ? 'behind' : 'above average')); // returns 'You are behind'
So can someone explain to me in simple language how this ternary operator will read?
In simple language, that ternary says, if $age > 10, consider 80 a good score, otherwise consider 50 a good score.
Rather than nesting ternaries, consider breaking out the nested logic into its own helper function. I find the following code much more understandable.
function adult_score($score) {
return $score > 80 ? "behind" : "above average";
}
function child_score($score) {
return $score < 50 ? "behind" : "above average";
}
$score = 10;
$age = 20;
echo $age > 10 ? adult_score($score) : child_score($score);
So, you understand a ternary, part before the ? is the if statement, part between ? and : is the "to do if truthy" and the part after : is the "to do if falsey". So if you took that ternary and wrapped the "if" part with an if statement and wrapped the "true" and "false" with curly braces and replaced the : with an else, you end up with this:
if($age > 10){
if($score < 80){
return 'behind';
} else {
return 'above average';
}
} else {
if($score < 50){
return 'behind';
} else {
return 'above average';
}
}
Like others have said though, it is ugly and hard to follow. Unless your goal was to make it hard for others to follow your code, then don't do this. Just please, don't. They are nice for one off if statements, but get confusing fast. Do yourself and any future readers of your code a favor.
Is there a way to optimize something like this?
I have already tried and it doesn't work (at least in php)
$foo = 6;
if ($foo != (3 or 5 or 10)) echo "it work";
elseif($foo < (5 or 10)) echo "it work again";
else echo "it doesn't work;"
I want to know if there's a better way to write that kind of validations.
But if something like this work in other langs, please let me know.
EDIT:
answer for this
($foo != (3 or 5 or 10)) -> in_array($foo,array(3,5,10))
does the same work if i want something like
($foo != (3 and 5 and 10))
No. It's not. You're testing your $foo value against the BOOLEAN result of those or operations. It'll boil down to
if ($foo != (true or true or true))
which is simply
if ($foo != true)
if (!$foo)
If you want to test a single value against multiple values, you can try
if(!in_array($foo, array(3,5,10))) { ... }
instead. For your < version, this won't work. You'll have to test each value individually:
if (($foo < 5) or ($foo < 10)) { ... }
though technically this is somewhat redundant, since if $foo is less than 5, it's already less than 10.
For the first you can use
if(!in_array($foo, [5,10,15]))
The second thing doesn't work in any language cause less then 5 or 10 is true for every thing less than 10. So no need for the 5. But I get your point. I don't know a fast way doing this
In python you can do this:
if(5 < x < 10)
a, b = b, a // swapping these two
I agree with the other answers and also, if you have more processing to do, you could also do something like this:
<?php
$x = 3;
switch ($x)
{
case 6:
$x = 5;
case 3:
case 7:
$x = 5;
case 5:
echo 'It is working' . PHP_EOL;
break;
}
EDIT: Thanks DanFromGermany for pointing the stacked cases. Added them as an example.
I am trying to convert the following code into a Ternary Operator, but it is not working and I am unsure why. I think my problem is that I do not know how to express the elseif operation in ternary format. From my understanding and elseif is performed the same way as an if operation by using the format : (condition) ? 'result'.
if ($i == 0) {
$top = '<div class="active item">';
} elseif ($i % 5 == 0) {
$top = '<div class="item">';
} else {
$top = '';
}
$top = ($i == 0) ? '<div class="active item">' : ($i % 5 == 0) ? '<div class="item">' : '';
$top = ($i == 0) ? '<div class="active item">' : (($i % 5 == 0) ? '<div class="item">' : '');
you need to add parenthesis' around the entire else block
The Ternary Operator doesn't support a true if... else if... else... operation; however, you can simulate the behavior by using the following technique
var name = (variable === 1) ? 'foo' : ((variable === 2) ? 'bar' : 'baz');
I personally don't care for this as I don't find it more readable or elegant. I typically prefer the switch statement.
switch (variable) {
case 1 : name = 'foo'; break;
case 2 : name = 'bar'; break;
default : name = 'bas'; break;
}
Too late probably to share some views, but nevertheless :)
Use if - else if - else for a limited number of evaluations. Personally I prefer to use if - else if - else when number of comparisons are less than 5.
Use switch-case where number of evaluations are more. Personally I prefer switch-case where cases are more than 5.
Use ternary where a single comparison is under consideration (or a single comparison when looping), or when a if-else compare is needed inside the "case" clause of a switch structure.
Using ternary is faster when comparing while looping over a very large data set.
IMHO Its finally the developer who decides the trade off equation between code readability and performance and that in turn decides what out of, ternary vs. if else-if else vs. switch-case, can be used in any particular situation.
//Use this format before reducing the expression to one liner
$var=4; //Change value to test
echo "Format result: ";
echo($var === 1) ? 'one' : //if NB.=> $varname = || echo || print || var_dump(ternary statement inside); can only be (placed at the start/wrapping) of the statement.
(($var === 2) ? 'two' : //elseif
(($var === 3) ? 'three' : //elseif
(($var === 4) ? 'four' : //elseif
'false' //else
))); //extra tip: closing brackets = totalnumber of conditions - 1
// Then echo($var === 1)?'one':(($var === 2)?'two':(($var === 3)?'three':(($var === 4)?'four':'false')));
echo "<br/>";
var_dump("Short result: ", ($var === 1)?'one':(($var === 2)?'two':(($var === 3)?'three':(($var === 4)?'four':'false'))) );