I've perused the questions on ternary operators vs. if/else structures, and while I understand that under normal circumstances there is no performance loss/gain in using ternary operators over if/else structures, I've not seen any mention of this situation. Language specific to PHP (but any language agnostic details are welcome) does the interpreter reassign values in situations like this:
$foo = 'bar'
$foo = strlen($foo) > 3 ? substr($foo, 0, 3) : $foo;
Since this would evaluate to $foo = $foo; is this inefficient, or does the interpreter simply overlook/discard this evaluation?
On a side note, what about:
!defined('SECURE') ? exit : null;
I don't know if your first example is inefficient, but it sure is pointless. I still think an if statement is clearer:
$foo = 'bar';
if (strlen($foo) > 3)
$foo = substr($foo, 0, 3);
And while the following works, it makes no sense to place null at the end because a ternary operator is meant to be used to evaluate expressions/values, but here null does nothing other than to prevent a parse error:
!defined('SECURE') ? exit : null;
More commonly, you would see this, an example of boolean short-circuiting (or exit doesn't execute if SECURE is not defined, because the or conditional expression evaluates to true automatically once at least one condition is found to be true):
defined('SECURE') or exit;
The point I'm trying to make is this: don't use ternary conditional expressions just because you can.
In this cases, I use the form presented by BoltClock:
if (strlen($foo) > 3) {
$foo = substr($foo, 0, 3);
}
PHP does not implement something more simple to work in this cases, yet :/
The topic that using a ternary here is not optimal has already been covered above. I'm going to address your question about whether it will reassign the value:
This depends on what you call "reassigning". PHP does not optimize, so the $foo = $foo will be evaluated. On the other hand this will not cause PHP to copy the value of $foo to a new chunk of memory. Probably PHP will just increase the refcount on $foo and then immediately decrease it (though I'm not sure about the exact implementation details of self-assignment). So, even though PHP will execute the statement, it won't affect performance (unless you choose to write $foo = $foo seven million times in your code).
There is always short-circuiting, although as #BoltClock said, an if statement is probably more readable in my opinion, and opens the door to else if and else conditions as well.
strlen($foo) > 3 && $foo = substr($foo, 0, 3);
The latter statement will only be executed if the former evaluates to TRUE.
Related
Pretty sure there's a simple answer to this but difficult to search on because of the vague terms used.
I'm using shorthand if statements and want to do more than one action when it returns true, what does the syntax look like?
For example, logically thinking I tried something like:
<?php
$var = "whatever";
(isset($var) ? $var2=$var; $var3=$var : $error="fubar");
?>
Obviously this stops with unexpected ; but hopefully you get the idea of what I'm trying to accomplish.
So sorry if this is a duplicate question, I swear I searched for it. :)
Thanks!
EDIT
I understand that whether or not shorthand is appropriate for this situation should be questioned. But still, can it be done, is the question.
Yes it's possible by using && between each assignment:
(isset($var) ? ($var2=$var) && ($var3=$var) : $error="fubar");
In the above code, if $var is set, $var2 and $var3 will get the same value, otherwise the two variables will not be changed.
That said, it is not the most appropriate method. The ternary operator should be used for simple logic, when the logic starts to get complicated, ternary is most likely no longer the best option. Instead you should just use a simple if/else.
For this specific instance, you can do this:
In this specific instance you can use this:
$output = (isset($var)) ? $var2 = $var3 = $var : false;
Slightly better option for this specific test instance:
$error = (isset($var)) ? !(bool)($var2 = $var3 = $var) : true;
This will set $error to true IF $var is not set, and to false if $var is set, so you could follow this up with an if($error) block.
However, ternary probably isn't the best way to approach this...
For more complicated instances you'd need to use closures or, worse, predeclared functions:
$output = (isset($var)) ? setVars($var) : false;
function setVars($var) {
$var2 = $var3 = $var;
}
At this point, you're probably better off with if or switch statements.
As far as I know, it is not possible, and shouldn't be possible. (?:) is not, and should not be taken as a if, because it doesn't works the same way, and is not designed for it.
The ternary operator exist as a way to return a value depending of a condition, not as a "quick" if.
If you are using it without needing the return value, then you probably are using it wrong.
In this specific case, you should be using and if-else statement. It would also help making your code more readable.
I need to assign one of two variables to a third variable, using the value of the second variable if the first is (bool)false or undefined.
I usually do this using ternary notation like so:
$foobar = ($some_prefix_and_some_variable_name) ? $some_prefix_and_some_variable_name : $bar ;
but sometimes this is not so pretty if the $foo variable name is very long, as it needs to be repeated in this notation.
My question is now, is it just as good to use this notation:
$foobar = $some_prefix_and_some_variable_name OR $foobar = $bar;
and is this notation interchangeable with the ternary version?
In PHP 5.3 there is also the short ternary notation:
$foobar = $fooooooooooooooooooooooooo ?: $bar ;
Because $foobar = $foo OR $foobar = $bar; evaluates to this:
Assign foo to foobar.
* Is there a value there?
* If not, assign bar to foobar.
While the other evaluates to:
Is there a value at foo?
* If so assign foobar = foo
* else assign foobar = bar
In the first example, if !foo you are assigning twice, if foo it can be faster. In the second example, you are only setting the value once total. I'll wager though that the speed difference is negligible.
The bigger issue here is readability. If 5.3 short notation isn't available, then I would still use the ternary notation if only because other programmers expect it.
For that matter, you will save more time and money by using the traditional ternary syntax if only because when people see your code they won't be asking themselves, WTF?
Since PHP 5.3 there is a special operator for this:
$foobar = $fooooooooooooooooooooooooo ?: $bar;
From the documentation on the ternary operator:
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.
in matter of speed, this:
$foobar = $fooooooooooooooooooooooooo OR $foobar = $bar;
it's faster
No.
I don't know for sure whether the two notations are interchangeable, which means that you should not use the second one! Whether or not they are actually the same, if it is not immediately clear what the code does (as in this case), you should change it, unless you are absolutely sure that no one else will ever have to update this code. If I saw that written, I wouldn't be sure whether it was supposed to be like this, or whether there was some typo, and the bug was simply never discovered (seen it too many times!).
Ideally, with very long variable names, you should do this:
if($fooooooooooooooooooooooooo){
$foobar =$fooooooooooooooooooooooooo;
} else {
$foobar = $bar;
}
Just to make it easy to read, unless speed is of the essence, in which case you should use the ternary operator.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
PHP - and / or keywords
PHP shorthand syntax
Quick question. I keep seeing shorthand expressions in libraries around the place, and despite having been a PHP developer for over 3 years, I struggle to quite see how the following would evaluate.
What exactly does the PHP interpreter do with the following shorthand lines of code when it encounters them?
<?php
defined('foo') OR exit('foo is not defined!');
$foo AND $this->bar();
I'm guessing that it' obviously conditional execution - i.e. the second statement won't get executed unless the first bit is true... but the use of the bitwise operators confuse me a bit.
Can someone elaborate?
Thanks :)
I believe that this is a form of short-circuit evaluation: http://en.wikipedia.org/wiki/Short-circuit_evaluation
Essentially, when evaluating an entire expression, the interpreter short circuits once it is certain of the result. For example:
true OR do_something();
This expression never calls do_something() because the first operand of OR is true, so the entire expression must be true.
Back when I was learning PHP I remember reading the 'do or die' style commands and not fully understanding them at the time, the classic example is:
mysql_connect() or die('couldn\'t connect');
Bear in mind that the conditions will only run if they're required, for example:
if (a == b && b == c)
Here b == c will only be tested if a == b. The same theory applies to or:
if (a == b || b == c)
Now b == c will only be tested if a != b.
In this case you are relying on this order to run a command (exit or $this->bar()) in certain conditions.
Be Aware... exit() is a bad idea in this circumstance - if you exit('something went wrong') there's nothing anyone can do to hide this error from the user, also it's likely to issue a 200 OK HTTP status where a 500 Internal Server Error would be much more appropriate, I would consider something more like:
defined('foo') OR throw new Exception('foo is not defined!');
Here you have a chance to either catch the Exception or at least let PHP catch it and issue a 500 status.
Mat
Much less elaborate than you think. The or keyword is the same as ||, except it has lower precedence. See the corresponding PHP page for details.
The actual execution of this statement relies on a separate concept involving logical operators: short circuiting. This means that, in the case of or, the second statement is not evaluated if the first statement turns out to be true. (Since in a conditional, for instance, the entire condition would return true without ever needing to see the second half.)
Sometimes you have a function that looks something like:
function test()
{
$foo = TRUE;
$bar = FALSE;
return $foo && $bar;
}
In this case, if some does:
$bla = test();
if($bla) {
... do something
}
The "...do something" will not get executed, because the function as a whole returned false.
return $foo && $bar means that both variables have to be true in order for the function to return true.
On the other hand, if it stated: return $foo || $bar; then the function would return true, because at least one variable is true.
Is there difference between ternary operator and if condition in php ?
if yes, kindly provide.
The ternary operator is an operator, so it forms an expression. So it will have a value that you can assign to a variable or use however you want. It is used for simple situations where a variable can take two possible values depending on a condition.
For example: $status = $age > 18 ? 'adult' : 'child';
Although possible, you should not nest the ternary operator.
The control structure if is something absolutely different. The only thing they have in common that both evaluate a condition (true/false). if is used to execute code fragments based on the result of that condition. You will find yourself using if most of the time (in fact, you can live without the ternary). In certain situations, it is less code and more readable if you replace certain types of ifs with the ternary, like this one:
if ($age > 18) {
$status = 'adult';
} else {
$status = 'child';
}
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
$value = ($a < 0) ? 'minus' : 'plus';
also you can see one interesting question how multiple ternary works :
unusual ternary operation
If statements are faster than ternary, but in most cases it doesn't matter.
Here is a post on the performance of If statements vs ternary.
Summary: It's basically the same unless you are evaluating large objects because ternary copies the objects being evaluated. This was using PHP 5.3 I'm not sure if it has been changed in current versions.
The ternary operator can do anything that an if/else statement can. In some cases it can provide brevity and expressiveness, but beware: it is easily abused.
One thing I like it for is checking for null:
$foo = (is_null($bar)) ? 0 : $bar->someNumber();
If my PHP memory serves me correctly, then it can also be used on an lvalue:
((is_null($foo)) ? $bar : $foo) = $quux;
It can be easily overdone though, such as in this C++ example, where it is used in place of loops and if/else statements:
while( ( ! printingStars) ?
( ( ! reachedMax) ?
( ( ++numberOfStars == n - 1) && (reachedMax = 1) )
: --numberOfStars ), printingStars = 1, starsLeft = numberOfStars
: ( ( ! starsLeft ) ?
printingStars = 0, (std::cout<< std::endl), 1
: --starsLeft, (std::cout<< "*"), 1 ) );
Use with caution.
Maybe another point of view: Performance.
A while ago I noticed that the ternary operator is faster than an if(). I don't know if this still applies to the latest versions of PHP.
< wild guess >
The reason may be that an if() allows more flexibility like using code blocks ({ }). A ternary operator basically is just testing an expression and grabbing a value depending on the result of the test.
Going back into my Assembler-days I'd say that an if() has to jump in memory and, therefore, takes a bit more time to do things.
< /wild guess >
However, this may be become noticeable only if the code is executed a decent number (1k+) of times.
There is a big difference in maintenance, if you use none trivial logic.
If you have a difficult problem you need under circumstances much more time, to sove it, as if you have an 'if ... then' in your code. And be sure: it's happen!
The time is not a friend of ternary operator. Fast to write, but not fast to understand, if the years gone!
I want to set a variable to a value, but only if a condition is true.
Instead of doing the following:
if($myarray["foo"]==$bar){
$variablename=$myarray["foo"];
}
This can end up being quite long if the variable names are long, or perhaps it involves arrays, when it's quite simple what I want to do — set a value if a condition is true.
I would like to use the conditional operator, something like this:
$variablename=($myarray["foo"]=="bar")? $myarray["foo"]......
But this fails because I don't want the variable to be set at all if the statement is false.
Basically, what I'm trying to do is make the first example shorter. Perhaps the conditional operator is not the way though...
Does anyone have any suggestions?
It doesn't get much shorter than:
if($condition) $var = $value;
IMO, the best way to make your code sample shorter is:
if($myarray["foo"] == $bar)
$variablename = $myarray["foo"];
FYI, the name of the operator you're asking about isn't "the ternary operator", it's the conditional operator.
Since you ask, a way you could actually use the conditional operator to do what you're asking is:
$myarray['foo'] == $bar ? $variablename = $myarray['foo'] : null;
but that's somewhat horrifically ugly and very unmaintainable.
You could do this, but I wouldn't as it is pretty unreadable and stupid:
$myarray["foo"] == $bar ? $variablename = $myarray["foo"] : 0;
or
$myarray["foo"] == $bar && $variablename = $myarray["foo"];
Your right, ternary is not the way to go. It's there to handle the if and else part of the statement.
Just stick with the regular if statement.
if($myarray["foo"]==$bar) $variablename=$myarray["foo"];
The "problem" you have isn't really a problem. Your example code is very clear and maintainable. I would really say leave it like it is.
You -could- remove the braces, but that will have an impact on maintainability.
Your other alternative is to create a set_if_true(mixed array, string key, boolean conditional) wrapper function. It hides what is really happening but depending on your specific implementation it is a good option. (For instance a configuration type object, or caching backend)
Put != instead of == and ?: instead of just ?..
$variablename = ($myarray["foo"] != "bar") ?: $myarray["foo"];
is the same as
if($myarray["foo"] != "bar"){} else { $variablename = $myarray["foo"]; }
It might not be the smartest solution but it works. I like this one more
if($myarray["foo"] != "bar") {$variablename = $myarray["foo"]};
Set the variable to itself in the false case:
$variablename=($myarray["foo"]=="bar")? $myarray["foo"] : $variablename
You can put the original expression in the else part of the ternary operation, but if you want to guarantee single evaluation of the expression then you'll have to use a temporary variable and an if statement.
Ternary isn't the way, even though it can be written so that ternary works.
The reason is this: you're trying to use it in a way it's not intended, which will make your code awkward for other developers to read.