I understand whiles, ifs, fors, cases, arrays, functions, and other syntactic constructs and my coding experience is 70’s style Fortran and T-SQL.
Now I’m trying to understand PHP, but it occasionally seems to compress several statements into one obfuscating line of code. What’s the expanded equivalent of the following single line of PHP below?
$start = gt("start") === false ? 0 : intval(gt("start"));
It is a ternary operator. They're usually of the following format:
expr1 ? expr2 : expr3;
Which means:
if expr1 then return expr2 otherwise return expr3
It can be visualized as follows:
Your code can be rewritten as:
if (gt("start") === false) {
$start = 0;
} else {
$start = intval(gt("start"));
}
It can improved as follows, to avoid an extra function call:
if (($result = gt("start")) === false) {
$start = 0;
} else {
$start = intval($result);
}
This ? is known as the ternary operator. It is a shorthand, e.g.
$x = a ? $b : $c; // where 'a' is some expression, variable or value
could also be written:
if (a) {
$x = $b;
}
else {
$x = $c;
}
Essentially, if expression a evaluates equal to TRUE, then the ternary operator returns b, otherwise it returns c.
Others have posted answers that do a good job of explaining the basics of how a ternary operator works, but to visualize what a ternary is versus an if/else you can do the following. Look at your example:
$start = gt("start") === false ? 0 : intval(gt("start"));
Now let’s make it one line using if/else:
if (gt("start") === false) { $start = 0; } else { $start = intval(gt("start")); }
When you see it lined up like that the immediate take-away—beyond the basic structure—is you must set $start = within each conditional.
So knowing that, them main benefit of a ternary operator is quick if/else logic to assign a value to a single variable.
The convenience of this from a coding standpoint is one can quickly disable that logic by just commenting out one line while debugging instead of having to comment out multiple lines of an if/else.
Related
Apologies if this is basic, but I'm learning php.
What does this snippet of code actually do? I've seen it in the source code for a plugin but can't quite figure out what's going on
$_POST['newName'] = $_POST['newName'] == "" ? "Dude" : $_POST['newName'];
Thanks.
This is a short version of if...else. This is a Ternary Logic.
$_POST['newName'] = $_POST['newName'] == "" ? "Dude" : $_POST['newName'];
if $_POST['newName'] == "" is true then "Dude" and else $_POST['newName'].
and both the value will be set in $_POST['newName'].
You can write this like this: [Full form]
if($_POST['newName'] == "")
$_POST['newName'] = "Dude";
The ? is also known as the ternary operator. It is called the ternary operator because it takes three operands - a condition, a result for true, and a result for false. If that sounds like an if statement to you, you are right on the money - the ternary operator is a shorthand (albeit very hard to read) way of doing if statements. Here's an example:
<?php
$agestr = ($age < 16) ? 'child' : 'adult';
?>
First there is a condition ($age < 16), then there is a question mark, and then a true result, a colon, and a false result. If $age is less than 16, $agestr will be set to 'child', otherwise it will be set to 'adult'. That one-liner ternary statement can be expressed in a normal if statement like this:
<?php
if ($age < 16) {
$agestr = 'child';
} else {
$agestr = 'adult';
}
?>
So, in essence, using the ternary operator allows you to compact five lines of code into one, at the expense of some readability.
Sometimes while coding, you might feel that writing an if(...){...}else{...} might feel like overkill for small amounts of code:
$result;
if (20>3)
{
$result = "bigger!";
}
else
{
$result = "smaller!";
}
So for this reason, a short hand notation was created where you would be able to express the exact same statement but without the need for such a big structure:
$result = (20>3) ? "bigger!" : "smaller!" ;
Whatever is between = and ? would then be the condition that is normally between the ( and ) of if(...). If that expression then equates to true, the value obtained by $result would be: "bigger!", and if it equated to false, the result would be: "smaller!".
As Frayne said, it is the shortened version of conditional statement. When we write it in full form, it becomes this:
<?php
if($_POST['newName'] == "") {
$_POST['newName'] = "Dude";
} else {
$_POST['newName'] = $_POST['newName'];
}
I'm trying to replicate this condition:
$sth = $this->getResult();
if($sth !== true){
return $sth;
}
with ternary operator I tried with;
($sth !== true) ? return $sth : ($sth == true) ? null;
But I got:
Expected colon
What you're ultimately trying to achieve is not possible with a ternary operator.
What you try to do is ONLY return in 1 situation, and continue the code in the other. The only way you could do this using a ternary operator is like this:
$result = ($sth !== true) ? true : false;
if ($result) return;
But that kinda defeats the purpose of the ternary operator.
In fact, your code has a couple of problems:
Ternary operator always needs 3 parts (*)
There is no need to check a condition twice, as that's the entire point of the operator
The operator returns a value, so you can't put a return inside the truthy or falsy part.
A ternary operator needs 3 parts
(condition) ? truthy result : falsy result
Note: Since PHP 5.3, it is possible to leave out the middle part of the ternary operator. Expression expr1 ?: expr3 returns expr1 if expr1 evaluates to TRUE, and expr3 otherwise. - source: php.net
No need to check things twice:
Again, let's take our operator:
($sth !== true)
? "I return if '$sth' is not true"
: "I return if '$sth' is true";
There is no need to have a 2nd check. You have both situations covered already. :)
No return values inside the truthy or falsy part
Finally: it is an operator that returns a value. You can't put a return in the truthy or falsy part, you need to put it in front of it:
return ($sth !== true)
? "I return if '$sth' is not true"
: "I return if '$sth' is true";
You have two '?'s in your code, and only one ':'. I believe that's the matter. You must have the same amount of question marks as you have colons.
The ternary operator is nice and useful, but it's not a block of commands. It is a decision on a value. Rule of thumb, if you can assign something as value to a variable you can use it within the ternary operator :
$var = 3; // valid
($condition?3:0); // valid
$var = return 3; //Invalid
($condition?return 3:null) //Invalid
You need to:
return ($sth !== true?$sth:null);
If you are using it to return from a function I would do it like so:
function testFunc()
{
//arbitrary setting of $sth only to explain the point
$sth = false;
//condition ? true : false
$outcome = ($sth === true) ? true : false;
return $outcome;
}
// false
var_dump(testFunc());
Remember, (condition) ? value if true : value if false;
You can also miss out the [value if true] parameter, like so:
$outcome = ($sth === true) ?: false;
That expression would assign the value of $sth to $outcome if $sth was true.
Your replacement code indeed misses a colon at the very end. It is syntactically incorrect.
If $sth !== true you return $sth. If not, you start a new ternary statement (that is not complete) which I cannot properly fathom. It now does not look at all like the original statement.
Given the following code:
if (is_valid($string) && up_to_length($string) && file_exists($file))
{
......
}
If is_valid($string) returns false, does the php interpreter still check later conditions, like up_to_length($string)?
If so, then why does it do extra work when it doesn't have to?
Yes, the PHP interpreter is "lazy", meaning it will do the minimum number of comparisons possible to evaluate conditions.
If you want to verify that, try this:
function saySomething()
{
echo 'hi!';
return true;
}
if (false && saySomething())
{
echo 'statement evaluated to true';
}
Yes, it does. Here's a little trick that relies on short-circuit evaluation. Sometimes you might have a small if statement that you'd prefer to write as a ternary, e.g.:
if ($confirmed) {
$answer = 'Yes';
} else {
$answer = 'No';
}
Can be re-written as:
$answer = $confirmed ? 'Yes' : 'No';
But then what if the yes block also required some function to be run?
if ($confirmed) {
do_something();
$answer = 'Yes';
} else {
$answer = 'No';
}
Well, rewriting as ternary is still possible, because of short-circuit evaluation:
$answer = $confirmed && (do_something() || true) ? 'Yes' : 'No';
In this case the expression (do_something() || true) does nothing to alter the overall outcome of the ternary, but ensures that the ternary condition stays true, ignoring the return value of do_something().
Bitwise operators are & and |.
They always evaluate both operands.
Logical operators are AND, OR, &&, and ||.
All four operators only evaluate the right side if they need to.
AND and OR have lower precedence than && and ||. See example below.
From the PHP manual:
// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;
// The constant false is assigned to $f before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;
In this example, e will be true and f will be false.
Based on my research now, PHP doesn't seem to have the same && short circuit operator as JavaScript.
I ran this test:
$one = true;
$two = 'Cabbage';
$test = $one && $two;
echo $test;
and PHP 7.0.8 returned 1, not Cabbage.
No, it doesn't anymore check the other conditions if the first condition isn't satisfied.
I've create my own short-circuit evaluation logic, unfortunately it's nothing like javascripts quick syntax, but perhaps this is a solution you might find useful:
$short_circuit_isset = function($var, $default_value = NULL) {
return (isset($var)) ? : $default_value;
};
$return_title = $short_circuit_isset( $_GET['returntitle'], 'God');
// Should return type 'String' value 'God', if get param is not set
I can not recall where I got the following logic from, but if you do the following;
(isset($var)) ? : $default_value;
You can skip having to write the true condition variable again, after the question mark, e.g:
(isset($super_long_var_name)) ? $super_long_var_name : $default_value;
As very important observation, when using the Ternary Operator this way, you'll notice that if a comparison is made it will just pass the value of that comparison, since there isn't just a single variable. E.g:
$num = 1;
$num2 = 2;
var_dump( ($num < $num2) ? : 'oh snap' );
// outputs bool 'true'
My choice: do not trust Short Circuit evaluation in PHP...
function saySomething()
{
print ('hi!');
return true;
}
if (1 || saySomething())
{
print('statement evaluated to true');
}
The second part in the condition 1 || saySomething() is irrelevant, because this will always return true. Unfortunately saySomething() is evaluated & executed.
Maybe I'm misunderstood the exact logic of short-circuiting expressions, but this doesn't look like "it will do the minimum number of comparisons possible" to me.
Moreover, it's not only a performance concern, if you do assignments inside comparisons or if you do something that makes a difference, other than just comparing stuff, you could end with different results.
Anyway... be careful.
Side note: If you want to avoid the lazy check and run every part of the condition, in that case you need to use the logical AND like this:
if (condition1 & condition2) {
echo "both true";
}
else {
echo "one or both false";
}
This is useful when you need for example call two functions even if the first one returned false.
Simple question. Here is this code.
$r = rand(0,1);
$c = ($r==0)? rand(65,90) : rand(97,122);
$inputpass .= chr($c);
I understand what it does in the end result, but I'd like a better explanation on how it works, so I can use it myself. Sorry if this is a bad question.
If you're unsure of what I'm asking about, its the (function?) used here:
$c = ($r==0)? rand(65,90) : rand(97,122);
That's called a ternary operator. It's effectively the equivalent of
if ($r == 0) {
$c = rand(65, 90);
} else {
$c = rand(97, 122);
}
But it's obviously a bit more compact. Check out the docs for more info.
That simply means:
if($r==0){
$c = rand(65,90);
else{
$c = rand(97,122);
}
If the statement is true the first operation after that ? is executed, else the operation after : is executed.
Its called a ternary operator.
Its the Ternary Operator
<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// The above is identical to this if/else statement
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to TRUE, and expr3 if expr1 evaluates to FALSE.
Since PHP 5.3, it is possible to leave out the middle part of the ternary operator. Expression expr1 ?: expr3 returns expr1 if expr1 evaluates to TRUE, and expr3 otherwise.
It's called the ternary operator. It's similar to an if/else construct, but the difference is that an expression using the ternary operator yields a value.
That is, you can't set a variable to the result of an if/else construct:
// this doesn't work:
$c = if ($r == 0) {
rand(65, 90);
} else {
rand(97, 122);
}
You can read more about it here: http://php.net/ternary#language.operators.comparison.ternary
The ternary operator is frequently misused. There's little benefit to using it in the example you showed. Some programmers love to use compact syntactic sugar even when it's not needed. Or even when it's more clear to write out the full if/else construct.
The ternary operator can also obscure test coverage if you use a tool that measures lines of code covered by tests.
I have this if statement that tests for the 2 conditions below. The second one is a function goodToGo() so I want to call it unless the first condition is already true
$value = 2239;
if ($value < 2000 && goodToGo($value)){
//do stuff
}
function goodToGo($value){
$ret = //some processing of the value
return $ret;
}
My question is about the 2 if conditions $value < 2000 && goodToGo($value). Do they both get evaluated or does the second one only get evaluated when the first one is true?
In other words, are the following 2 blocks the same?
if($value < 2000 && goodToGo($value)) {
//stuff to do
}
if($value < 2000) {
if (goodToGo($value)){
//stuff to do
}
}
No--the second condition won't always be executed (which makes your examples equivalent).
PHP's &&, ||, and, and or operators are implemented as "short-circuit" operators. As soon as a condition is found that forces the result for the overall conditional, evaluation of subsequent conditions stops.
From http://www.php.net/manual/en/language.operators.logical.php
// --------------------
// foo() will never get called as those operators are short-circuit
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
Yes. The two blocks are the same. PHP, like most (but not all) languages, uses short-circuit evaluation for && and ||.
The two blocks ARE same.
PHP logical operators are "lazy", they are evaluated only if they are needed.
The following code prints "Hello, world!":
<?php
$a = 10;
isset($a) || die ("variable \$a does not exist.");
print "Hello, world!"
?>
Other logical operators includes &&, and, or.
<?php
perform_action() or die ('failed to perform the action');
?>
is a popular idiom.
the second condition will only be checked if and only if first one is true, hence both statements are equivalent.
Yes, the 2 code blocks you gave are equivalent. PHP has short-circuiting, so when you use
|| and &&, any statement after the first only gets evaluated when necessary.
Always corelate your technical Language with your own language, Likewise here, If I say you in verbal conversation, its just like :You are asking= "if I am hungry '&&' I am eating Pizza" is similar to "If I am hungry then only i am eating Pizza"?
So here you can see that later phrase says that untill i am not hungry i am not eating pizza, and the former says I am humgry and I am eating pizza.
:-)