I am having trouble understanding the behavior of the 'and' PHP operator.
Here is the code:
$condition1 = true;
$var2 = "var2";
$var3 = "var3";
$condition2 = $condition1 and $var2 == $var3;
if($condition2)
echo '$condition1 and $var2 == $var3';
Output: $condition1 and $var2 == $var3
Now it is obvious that since $var2 != $var3, $condition2 should be false. Hence the echo statement should not be executed but it happens the other way. Can any one tell me what's wrong with this code?
Use && instead of and.
and has lesser precedence than &&. The statement
$condition2 = $condition1 and $var2 == $var3;
is executed in two steps from left to right.
1: $condition2 = $condition1 is executed. i.e. $condition2 is true now.
2: $var2 == $var3; is executed which performs the evaluation but does not assign any value to any variable.
I think this is an operator precedence issue. Try this instead:
$condition2 = ($condition1 and $var2 == $var3);
I think the issue is that your current code gets interpreted like this:
($condition2 = $condition1) and ($var2 == $var3)
Try this
$condition2 = ($condition1 and $var2 == $var3);
Or this one
$condition2 = ($condition1 && $var2 == $var3);
Related
In PHP, I have seen a lot of people using the this:
if($var1 = myfunction()){
//do something
}
That way, if true the variable already holds the value you need.
Why doesn't the same work with two variables and two functions?
if($var1 = myfunction() && $var2 = myfunction2()){
// Do something
}
When i tried using the above, I always got a "1". Even though both functions return a value. As soon as I removed the second part ($var2 = ) - it worked.
Why do I get a 1?
It's because of operator precedence
php interprets
$var1 = myfunction() && $var2 = myfunction2()
expression as
$var1 = ( myfunction() && ( $var2 = myfunction2() ) )
So:
$var2 = myfunction2() comes first
Then myfunction() && $var2 is evaluated
The result of the latter expression (which is always a boolean) is assigned to $var1
The solution - use parentheses
($var1 = myfunction()) && ($var2 = myfunction2())
The better solution: avoid such expressions
How would someone neatly check if 4 variables are the same?
Obviously this wouldn't work:
if ($var1 === $var2 === $var3 === $var4)
But what would, without writing loads of code?
One way to go would be this:
if ($var1 === $var2 && $var2 === $var3 && $var3 === $var4)
Not a huge amount of code and it gets the job done.
if(!array_diff([$var2, $var3, $var4], [$var1])){
// All equal
}
if ($var1 === $var2 && $var3 === $var4 && $var1 === $var3)
You don't need to check if 2 and 4 are equal
Using array_unique you can check if the array of unique values from the variable list is 1 (which means they are all equal):
if (count(array_unique([$var1, $var2, $var3, $var4])) == 1)
// all equal
This comes in handy especially when comparing a long list of variables, compared to a long list of == checks in an if statement.
You can use ! as your master and use &&
if($var1===$var2 && $var1 === $var3 && $var1 === $var4)
But this wont let you know which of the 4 is not like the others.
In case you are dealing with many variables, I played with the below code and it works.
$m = 'var'; //Assuming you know the variable name format $var1, $var2, $var3,...
for( $n = 1; $n <= 3; $n++) { //testing for 4 variables
$v = "$m$n";
$n++;
$w = "$m$n";
if ( $$v !== $$w ) {
echo "false";
break;
}
$n--;
}
//Breaks and echo "false" as soon as one of the variables is not equal
//Note: increase the iteration for more variable.
$var4 = 123;
function fn1($p1)
{
return array('p1' => 1, 'p2' => 2);
}
if ($var1 = fn1(1) AND $var4 == 123)
{
print_r($var1);
}
if ($var2 = fn1(1) && $var4 == 123)
{
print_r($var2);
}
if (($var3 = fn1(1)) && $var4 == 123)
{
print_r($var3);
}
If you run this simple script it will output strange results, at
least for me!! First output from first if expression will result in
an array returned from the function & assigned to the $var1
variable, which is what I'm expecting, well?
Second output from second if expression will result in an integer
'1' assigned to the $var2 variable, which is NOT expected at all!!
Please note that the only changed thing is the logical operator,
I've used '&&' rather than 'AND', that's all!!
Third output from third if expression will result again the expected
array returned from the function & assigned to the $var3 variable,
exactly as the first if expression, but wait: I've just embraced the
assignment statement in the if expression within brackets, while
still using the second if expression code!!
Can anyone explain technically -in details- why this strange behavior? php.net reference links will be appreciated.
I know that '&&' has higher precedence than 'AND' but that doesn't explains it to me!!
PHP: Operator Precendence
&& has a higher precedence than =, so in the second if, you are assigning the value of fn1(1) && $var4 == 123 (true or false) to $var2.
In the first if, AND has a lower precedence than =, so the assignment happens first, then the result is compared.
In the third if, the assignment happens first again because everything in parens gets processed first.
&& has a higher precedence than =, so what's really happening is something more like:
if ($var1 = (fn(1) && $var4 == 123))
So what is really being assigned to $var1 is the boolean result, which is why you get 1.
PHP's AND and && operators both are logical ands, but the and version has a lower binding precedence, see: http://php.net/manual/en/language.operators.precedence.php
I'd like to do this:
$var = ($var2 . $var3)
This means $var is only true if $var1 and $var2 are truthy (anything that will cast to a boolean true).
Do it like this:
$var = ($var2 && $var3);
or simply like SQL:
$var = ($var2 and $var3);
Read more about Logical Operators and how to use them at PHP manual. Both && and and operators are good enough for it, the only difference being the precedence.
. is the string concatenation operator. Use && for a boolean AND operation:
$var = $var2 && $var3;
$var = isset( $var2 ) && isset( $var3
);
?
if ($var == ($var1 || $var2))
{
...
}
I am considering using this, but am ont sure if it is valid, and there doesn't seem to be somewhere to check.
It seems logically consistent to me but am not sure, and I don't have something to test it on close by.
If it is valid, what other mainstream languages support this sort of construct.
EDIT: The comparison is valid, but not in the way I was thinking.
What I was trying to do was actually the in_array() function, which I just discovered.
Your code is syntactical valid but semantical probably not what you wanted.
Because $var1 || $var2 is a boolean expression and always yields true or false. And then $var is compared to the result of that boolean expression. So $var is always compared to either true or false and not to $var1 or $var2 (that’s what you’re have probably expected). So it’s not a shorthand to ($var == $var1) || ($var == $var2).
Now as you already noted yourself, in_array is a solution to this problem if you don’t want to write expressions like ($var == $var1) || ($var == $var2), especially when you have an arbitrary number of values you want to compare to:
in_array($var, array($var1, $var2))
Which is equivalent to:
($var == $var1) || ($var == $var2)
If you need a strict comparison (using === rather than ==), set the third parameter to true:
in_array($var, array($var1, $var2), true)
Which is now equivalent to:
($var === $var1) || ($var === $var2)
Yes, the corrected version is valid syntax:
if ($var == ($var1 || $var2))
Question is, what does it mean?
It will compare the result of the expression ($var1 || $var2) which will be a boolean, to the value of $var.
And, as mentioned, php -l file.php will tell you if there are any syntax errors.
Edit:
Consider this:
$var1 = 1;
$var2 = 2;
echo var_dump(($var1 || $var2));
Result is:
bool(true)
You can use the command php -l filename.php from the command line to check for syntax errors.
As George Marian says, it's missing a closing parenthesis so would throw a syntax error. It's otherwise valid, though, so I can't see that it's the logical OR construct itself that you're unsure about. It's used in several languages, including javascript.
your corrected example is valid and will be TRUE is $var is TRUE and either $var1 or $var2 is TRUE .. OR . if $var, $var1 and $var2 are all FALSE