Initializing a variable and using that in the if clause - php

if($y=3){echo $y;} and if($y=1 and $y>2){echo $y;} work as expected. However, I wonder why it's not possible to use this if($x=1 && $x>3){echo $x;} , which returns Notice: Undefined variable: x. (and operator has higher precedence than &&) If && first evaluates the right operand and after that evaluates the left hand shouldn't it work?

$y=1 and $y>2 works as you expected because:
As per operator precedence rule, = has higher precedence than and. So, it evaluates as:
($y = 1) $y>2
So, assignment takes place. (Expression inside parentheses evaluates first)
$x=1 && $x>3 doesn't work as you expected because:
As per operator precedence rule, && has higher precendence than =. So, it evaluates as:
$x=(1 && $x)>3
Naturally, $x is compared with 1 which is undeclared initially. So the undefined variable error pops up. So if you want to change the order, change the expression to:
($x=3) && $x>2
So your if will look like:
if(($x=3) && $x>2) {
echo $x;
}

if($y=1 and $y>2){echo $y;}
"=" assignment operator has higher precedence than "and".
"=" assignment operator initialize $y and works as expected.
if($x=1 && $x>3){echo $x;}
"=" assignment operator has lower precedence than "&&".
"&&" operator execute before assignment, hence in this case $x is not defined/initialized and which returns Notice : Undefined variable : x.

Related

logical vs assignment operator precedence in PHP

Recently i came upon such snippet:
$x = 2 && $y = 3; echo (int)$x.':'.(int)$y;
Which produces output 1:3.
By looking at operator precedence sheet i see that logical operators || and && has higher precedence than assignment operator =. So first expression should be evaluated as $x = (2 && $y) = 3; which becomes $x = (2 && null) = 3; and finally evaluates to $x = false = 3; Secondly - assignment operator has right associativity, so interpreter should try to execute false = 3 which is illegal of course. So in my opinion above mentioned code snippet should not compile at all and must throw parse or run-time error. But instead of that script produces 1:3. Which means that interpreter executed actions are:
a) $y=3
b) 2 && $y
c) $x = (2 && $y)
Why it is so and not according to operator precedence ?
The operator precedence sheet you link to states as a separate note:
Although = has a lower precedence than most other operators, PHP will
still allow expressions similar to the following: if (!$a = foo()), in
which case the return value of foo() is put into $a.
So, in effect, an assignment inside an expression will be treated somewhat like a sub-expression. Exactly how and when this will happen isn't clear from the documentation, which just states that "similar" expressions will work this way.

how ordering makes a difference within an expression for an if statement

I have an array ...
$a= array(1,2,3,4);
if (expr)
{ echo "if";
}
else
{ echo 'else';
}
When expr is ( $a = '' || $a == 'false') , output is "if" ,
but when expr is ( $a == 'false' || $a = '' ) , output is "else"
Can anyone explain why & how ordering makes a difference ??
Edit : I understand that I am assigning '' to $a. That is not the problem. The real question is : What does the expression $a = '' return? And why does reversing the order of the 2 situations switch us from the IF section to the ELSE section?
AGAIN : I UNDERSTAND I AM ASSIGNING NOT COMPARING. PLEASE ANSWER THE QUESTION AS IS.
First, never use = as a comparison operator. It is an assignment operator.
The difference is that false (as a boolean) is not the same as 'false' as a string.
Certain expressions are type juggled by PHP to evaluate somewhat differently to how you would expect.
false==""
// TRUE.
false=="false"
// FALSE.
Additionally, when you try to compare numbers to strings, PHP will try to juggle the data so that a comparison will be performed. There is a lot to it (much more than I will post here) but you would do well to investigate type juggling and various operators. The docs are a great start for this. You should also have a read of the comparison operators which go into a lot of detail about how various comparisons will work (depending on whether you use == or === for example).
With $a = '' you are setting $a to an empty string. This is the same as:
$a = '';
if($a){
echo 'if';
}
The || operator checks if the first condition is true and if it is, it continues with the code in the brackets. In PHP, if $a is set to anything, it will return true. In the second case $a does not equal the string 'false' (you are not comparing it to a boolean false even!), so it executes the code in the else part.
And Fluffeh is not entirely correct. You can use the assignment operator in an if condition very effectively, you just have to be smart about it.
$a = '' is an assignment: you have, in error, used = in place of ==. Assignment is an expression which has the value of the thing your assigning.
A single equals sign = is the assignment opporator, so $a = '' is assigning an empty string to $a not checking if it is equal to.
In your 1st example you set the value of $a to an empty string, then check if it is false. An empty tring evalutes to false in php, so the conditional is true.
In your second example, you check if $a equals false 1st (when the value of $a is an array), so the conditional is false

PHP Logical Operators precedence affects variable assignment results strangely

$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

The strange ways of the "or" in PHP

PHP's or is an weird keyword. Here it is in a code snippet that makes me confused:
echo 0 or 1; // prints 1
$foo = (0 or 1);
echo $foo; // prints 1
$foo = 0 or 1;
echo $foo; // prints 0 for some reason
Why does the last one print 0 and not 1?
This is because of different operator precedence. In the third case, the assignment is handled first. It will be interpreted like this:
($foo = 0) or 1;
The || operator has a different precedence. If you use
$foo = 0 ||1;
It will work as you expect.
See the manual on logical operators
No, I wouldn't, that's because of operator precedence:
$foo = 0 or 1;
// is same as
($foo = 0) or 1;
// because or has lower precedence than =
$foo = 0 || 1;
// is same as
$foo = (0 || 1);
// because || has higher precedence than =
// where is this useful? here:
$result = mysql_query() or die(mysql_error());
// displays error on failed mysql_query.
// I don't like it, but it's okay for debugging whilst development.
It's ($foo = 0) or 1;. or has a lower operator precedence than = .
You should use || in this case, since it has a higher precedence than =, and thus will evaluate as you'd expect.
IIRC, the assignment operator (=) has higher precedence than or. Thus, the last line would be interpreted as:
($foo = 0) or 1;
Which is a statement that assigns 0 to $foo, but returns 1. The fist statement is interpreted as:
echo(0 or 1);
An as such will print 1.
Order of operations. The word "or" has much lower precedence than the corresponding "||". Lower, even, than the assignment operator. So the assignment happens first, and the value of the assignment is the first operand to the "or".
"or" is meant more to be used for flow control than for logical operations. It lets you say something like
$x = get_something() or die("Couldn't do it!");
if get_something is coded to return false or 0 on failure.
In the first two snippets, you are comparing 0 or 1 (essentially true or false). In the third snippet you are assigning 0, which works, and thus is true, so therefore the or condition is not executed.emphasized text
In your third example, the = operator has a higher precedence than or, and thus gets done first. The || operator, superficially the same, has a higher precedence than =. As you say, interesting.

'AND' vs '&&' as operator

I have a codebase where developers decided to use AND and OR instead of && and ||.
I know that there is a difference in operators' precedence (&& goes before and), but with the given framework (PrestaShop to be precise) it is clearly not a reason.
Which version are you using? Is and more readable than &&? Or is there no difference?
If you use AND and OR, you'll eventually get tripped up by something like this:
$this_one = true;
$that = false;
$truthiness = $this_one and $that;
Want to guess what $truthiness equals?
If you said false... bzzzt, sorry, wrong!
$truthiness above has the value true. Why? = has a higher precedence than and. The addition of parentheses to show the implicit order makes this clearer:
($truthiness = $this_one) and $that
If you used && instead of and in the first code example, it would work as expected and be false.
As discussed in the comments below, this also works to get the correct value, as parentheses have higher precedence than =:
$truthiness = ($this_one and $that)
Depending on how it's being used, it might be necessary and even handy.
http://php.net/manual/en/language.operators.logical.php
// "||" has a greater precedence than "or"
// 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 and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;
But in most cases it seems like more of a developer taste thing, like every occurrence of this that I've seen in CodeIgniter framework like #Sarfraz has mentioned.
Since and has lower precedence than = you can use it in condition assignment:
if ($var = true && false) // Compare true with false and assign to $var
if ($var = true and false) // Assign true to $var and compare $var to false
For safety, I always parenthesise my comparisons and space them out. That way, I don't have to rely on operator precedence:
if(
((i==0) && (b==2))
||
((c==3) && !(f==5))
)
Precedence differs between && and and (&& has higher precedence than and), something that causes confusion when combined with a ternary operator. For instance,
$predA && $predB ? "foo" : "bar"
will return a string whereas
$predA and $predB ? "foo" : "bar"
will return a boolean.
Let me explain the difference between β€œand” - β€œ&&” - "&".
"&&" and "and" both are logical AND operations and they do the same thing, but the operator precedence is different.
The precedence (priority) of an operator specifies how "tightly" it binds two expressions together. For example, in the expression 1 + 5 * 3, the answer is 16 and not 18 because the multiplication ("*") operator has a higher precedence than the addition ("+") operator.
Mixing them together in single operation, could give you unexpected results in some cases
I recommend always using &&, but that's your choice.
On the other hand "&" is a bitwise AND operation. It's used for the evaluation and manipulation of specific bits within the integer value.
Example if you do (14 & 7) the result would be 6.
7 = 0111
14 = 1110
------------
= 0110 == 6
which version are you using?
If the coding standards for the particular codebase I am writing code for specifies which operator should be used, I'll definitely use that. If not, and the code dictates which should be used (not often, can be easily worked around) then I'll use that. Otherwise, probably &&.
Is 'and' more readable than '&&'?
Is it more readable to you. The answer is yes and no depending on many factors including the code around the operator and indeed the person reading it!
|| there is ~ difference?
Yes. See logical operators for || and bitwise operators for ~.
Another nice example using if statements without = assignment operations.
if (true || true && false); // is the same as:
if (true || (true && false)); // TRUE
and
if (true || true AND false); // is the same as:
if ((true || true) && false); // FALSE
because AND has a lower precedence and thus || a higher precedence.
These are different in the cases of true, false, false and true, true, false.
See https://ideone.com/lsqovs for en elaborate example.
I guess it's a matter of taste, although (mistakenly) mixing them up might cause some undesired behaviors:
true && false || false; // returns false
true and false || false; // returns true
Hence, using && and || is safer for they have the highest precedence. In what regards to readability, I'd say these operators are universal enough.
UPDATE: About the comments saying that both operations return false ... well, in fact the code above does not return anything, I'm sorry for the ambiguity. To clarify: the behavior in the second case depends on how the result of the operation is used. Observe how the precedence of operators comes into play here:
var_dump(true and false || false); // bool(false)
$a = true and false || false; var_dump($a); // bool(true)
The reason why $a === true is because the assignment operator has precedence over any logical operator, as already very well explained in other answers.
Here's a little counter example:
$a = true;
$b = true;
$c = $a & $b;
var_dump(true === $c);
output:
bool(false)
I'd say this kind of typo is far more likely to cause insidious problems (in much the same way as = vs ==) and is far less likely to be noticed than adn/ro typos which will flag as syntax errors. I also find and/or is much easier to read. FWIW, most PHP frameworks that express a preference (most don't) specify and/or. I've also never run into a real, non-contrived case where it would have mattered.

Categories