The following two ifs produced different results(first if echos hi, second does not), why? why didn't the variable assignment on $t work? is this due to $t's local scope inside the if conditional?
if(isset($_REQUEST["test"]) && $t=trim($_REQUEST["test"]) && !empty($t)){
echo 'hi'
}
if(isset($_REQUEST["test"]) && $t=trim($_REQUEST["test"])){
if(!empty($t))echo 'hi'
}
&& has a higher precedence than =, hence the first expression is evaluated as:
isset($_REQUEST['test']) && $t = (trim($_REQUEST['test']) && !empty($t))
Since !empty($t) is evaluated before anything is assigned to $t, the expression is false. You could fix this by explicitly setting parentheses, or by using a less awkward way to write it:
if (isset($_REQUEST['test']) && trim($_REQUEST['test'])) {
echo 'hi';
}
trim($_REQUEST['test']) will evaluate to true or false just by itself, no empty necessary. If you actually need the trimmed value later, you can save it like so:
if (isset($_REQUEST['test']) && ($t = trim($_REQUEST['test']))) {
echo 'hi';
}
If you make minor modification like this in your code:
if(isset($_REQUEST["test"]) && ($t=trim($_REQUEST["test"])) && !empty($t)){
echo '1: hi<br/>';
}
if(isset($_REQUEST["test"]) && $t=trim($_REQUEST["test"])){
if(!empty($t))
echo '2: hi<br/>';
}
Then both 1: hi and 2: hi will be printed. Difference is parenthesis around first $t assignment.
Related
I'm wondering, will this work with any major PHP versions?
if ($foo != $bar && '' != $str = some_function($some_variable))
echo $str;
The some_function($some_variable) returns a string, which is assigned to the $str variable and then checked if is an empty string. The $str variable is used later of course.
Will be the output of the some_function assigned to the $str variable in every major PHP version (>5)? I couldn't find any information on this. Thanks.
I'm currently running 5.4 and it's working.
Edit: To avoid further confusion, the $foo != $bar precedes the other expression because the $str variable is only used inside the if statement. Sorry, I forgot to clarify that.
Yes it does work, but to get it working like you want you have to put brackets around the assignment, because the comparison has a higher precedence then the assignment! (operator precedence)
Also if $foo != $bar is false the $str would never been initialize so also change the order, so that it get's assigned ever time.
So use this:
if ('' !== ($str = some_function($some_variable)) && $foo != $bar)
//^^^ ^ See here And here^
//| '!==' to also check the type
I would not see why this would not work in any PHP version (> 5).
Tested here: http://sandbox.onlinephpfunctions.com/code/a295189c50c191bbd0241d4e8ea4e3081cdb40ae
Worked with all the versions from 4.4.9 and up.
Note: Because you are using the && operator, the code after the && will not be run if $foo != $bar already returns false, since the second expression cannot change the outcome of the && operator, therefore it will simply ignore it.
If the assignment is intented to always take place, then change the order of the expressions.
if ('' != $str = some_function($some_variable) && $foo != $bar)
echo $str;
Why don't you make it clear and not confusing by using brackets and curly braces. Example:
if (($foo != $bar) && '' != ($str = some_function($some_variable)) ) {
echo $str;
}
I want to check whether the length of $a is 0 or if the length is not 0 then check if it is a numeric value in single IF statement in PHP. I tried this but not working
$a = '23bc';
if((strlen($a)===0 || (strlen($a)>0 && ctype_digit($a))) )
{
echo 'Good to Go';
}
else
{
echo 'Bad to Go';
}
I do not want to apply nested conditions here. Is it possible to do it in single IF statement?
I found this question here but this does not answers what I am asking for && (AND) and || (OR) in IF statements
It would be nice to know what your script is trying to achieve beyond using a one-liner in an if conditional concerning an empty string or a numeric string. With cytpe_digit() every character must evaluate as a number to qualify as a numeric string. You get a false result with '23bc' because of the 'bc' portion.
One of the problematic aspects with the script is that one don't know which condition results in a true. One or the other conditions could be true or they could both be false.
See demo: http://3v4l.org/8Pchk.
You could rewrite the code making use of a ternary expression to have a one liner which eliminates the if-else construct, as follows:
<?php
$a = '23bc';
if( strlen( $a ) != 0) {
echo ctype_digit( $a )? "Good to Go\n" : "Bad to Go\n";
}
The following may be more in line with what you're asking. Here's the ultimate one-liner:
<?php
echo ( !strlen($a) || ctype_digit($a) )? "Good to Go\n" : "Bad to Go\n";
Because of the strictness of the identity operator === if $a is null, then you you'll see "Bad to Go. You may either test for equality strlen($a) == 0 or you can be more succinct by using the ! operator (boolean NOT). See demo: http://3v4l.org/7cfV0
I'm a bit of an optimization freak (at least by my definition) and this question has been bugging me for quite a while.
I'm wondering if PHP does some optimization on && and ||:
Take the following example:
$a = "apple";
$b = "orange";
if ($a == "orange" && $b == "orange") {
//do stuff
}
When that code executes, it will check if $a is equal to "orange." In this case it isn't. However, there is an && operator. Since the first part ($a == "orange") already returned false, will PHP still check if $b is equal to "orange?"
I have the same question for ||:
$a = "orange";
$b = "orange";
if ($a == "orange" || $b == "orange") {
//do stuff
}
When it checks if $a is equal to "orange," it returns true. Since that would make the || operator return true, will PHP even check the second part of the || (since we already know it will be true)?
Hopefully I am making sense here, and hopefully somebody has an answer for me. Thank you!
PHP uses short circuit evaluation with binary conditionals (such as &&, || or their constant equivalents), so if the result of evaluating the LHS means the RHS isn't necessary, it won't.
For example...
method_exists($obj, 'func') AND $obj->func();
...is an exploitation of this fact. The RHS will only be evaluated if the LHS returns a truthy value in this example. The logic makes sense here, as you only want to call a method if it exists (so long as you're not using __call(), but that's another story).
You can also use OR in a similar fashion.
defined('BASE_PATH') OR die('Restricted access to this file.');
This pattern is used often as the first line in PHP files which are meant to be included and not accessed directly. If the BASE_PATH constant does not exist, the LHS is falsy so it executes the RHS, which die()s the script.
Yes, PHP short-circuits the && and || operators, meaning that no, the right operand won't be evaluated if the value of the left operand means that it doesn't need to be evaluated. There's no need to optimize them. You can test it like this:
function one() {
echo "One";
return false;
}
function two() {
echo "Two";
return true;
}
one() && two(); // Outputs One
echo "\n";
two() || one(); // Outputs Two
Here's a demo. If there were no short-circuiting, you'd get:
OneTwo
TwoOne
I came across some code today where a string is compared to two values at the same time. I've never seen this before - will this work? Can someone explain it to me?
$foo = 'date';
if ($foo == ('date' || 'datetime')) {
echo "Hello world";
}
That won't work. Write if ($foo == 'date' || $foo == 'datetime').
Not only won't || work for selecting from a set, but also you use used a single =, which is for assignment rather than comparison.
In this case, the constant strings are compared using the boolean or operator. To do that, they are both converted to boolean. Since they are non-empty strings, they evaluate to true. true or true returns true, which is assigned to $foo which is compared to $foo. That comparison will always be true if $foo is 'date' or 'datetime' or about any other non-empty string.
So, whatever the previous value of $foo was, or even if it wasn't assigned at all, the if-expression always evaluates to true, so you always get the echo, and $foo will always be true afterwards.
This'll not work. ('date' || 'datetime') always evaluates to true.
Use this instead:
$foo = 'date';
if ($foo == 'date' || $foo == 'datetime') {
echo "Hello world";
}
You could try the following:
$haystack = array("date","datetime");
$needle = "date";
if (in_array($needle,$haystack)) {
// do something
}
No. the || or OR operators only work with Booleans. you'll need this condition:
if ($foo == 'date' || $foo == 'datetime') { ... }
But what if you have 10 possible values? You'll need one for each? yes and no.
Another possibility is to insert all the possible values into an array and check whether your value is possible by comparing it to that array, using in_array():
$possible_values = array('date', 'datetime');
if (in_array($foo, $possible_values)) { ... }
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.