Below is something strange, I didn't get
if (print("foo") || print("bar")) {
// "foo" has been printed.
}
Why the output is 1?
Could please explain?
It's because PHP is a ridiculous language. print is not a normal function, it's a language construct. This line is actually parsed as:
if (print (("foo") || print("bar")))
And ("foo") || print("bar") is an expression which evaluates to 1. The string "foo" in a boolean context is true, so the || operator yields 1.
If you explicitly parenthesize the expression the way one would expect it to be parsed:
if ((print("foo")) || (print("bar")))
Then the output is what you would expect:
foo
Related
Example1:
if(!print("1") || 1){
echo "a";
}else{
echo "b";
}
Output
1b
The Example 1 is printing "1b" instead of "1a". According to me, inside if the final condition should be if(0 || 1) after solving !print("1").
But the Example 2 is printing "1a".
Example 2:
if((!print("1")) || 1){
echo "a";
}else{
echo "b";
}
Output
1a
Can you elaborate, why the or condition in the first statement didn't work.
The key thing here is to realise that print is not a function, and doesn't take arguments in parentheses - the parentheses aren't optional, they're just not part of the syntax at all.
When you write print("1"); the print statement has a single argument, the expression ("1"). That is if course just another way of writing "1" - you could add any number of parentheses and it wouldn't change the value.
So when you write print("1") || 1 the argument to print is the expression ("1") || 1. That expression is evaluated using PHP's type juggling rules as true || true which is true. Then it's passed to print and - completely coincidentally to what you were trying to print - is type juggled to the string "1".
The print statement is then treated as an expression returning true, and the ! makes it false, so the if statement doesn't run.
This is a good reason not to use parentheses next to keywords like print, require, and include - they give the mistaken impression of "attaching" an argument to the keyword.
Moving over to PHP from another language and still getting used to the syntax...
What's the proper way to write this statement? The manual on logical operators leaves something to be desired..
if($var !== '5283180' or '1234567')
Generally, comparison is by using == and the reverse is !=. But if you want to compare values along with its data type, then you can use === and the reverse is !==.
Please refer to the documentation for more information.
You can use the following:
if($var!='5283180' || $var!='1234567')
Try this
if($var != '5283180' || $var != '1234567')
PHP's or functions identically to the normal ||, but has a lower binding precedence. As such, these two statements:
$foo = ($bar != 'baz') or 'qux';
$foo = ($bar != 'baz') || 'qux';
might appear to be otherwise identical, but the order of execution is actually quite
different. For the or version, it's executed as:
($foo = ($bar != 'baz')) or 'qux';
- inequality test is performed
- result of the test is assigned to $foo
- result of the test is ORed with the string 'qux';
For the || version:
$foo = (($bar != 'baz') || 'qux');
- inquality test is performed
- result of test is ||'d with 'qux'
- result of the || is assigned to $foo.
To build on the others, as the OP mentioned they are new to PHP, there is a couple things to be considered.
First off, the PHP or that you're looking for is the double line (||) and each item must be a statement on each side of the ||.
if ( $var !== '5283180' || $var !== '1234567')
addition:
As mentioned in the PHP Manual
The or operator is the same as the || operator but takes a much lower precedence.
Such as the given example (from manual):
// The constant false is assigned to $f and then true is ignored
//Acts like: (($f = false) or true)
$f = false or true;
Now as mentioned, there is the general comparison (== or 'Equal') and the type comparison (=== or 'Identical'), with both having the reverse (not). In the given example, the test will check that $var is not identical to the values.
From PHP Manual:
$a !== $b | Not identical | TRUE if $a is not equal to $b, or they are not of the same type.
With this said, double check that this is what you're actually trying to accomplish. Most likely you're looking for !=.
$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
here is what i'm trying to achieve:
if $x is either of these 3 values: 100, 200 or 300 - do something
I'm doing this:
if($x==("100"||"200"||"300"))
{
//do something
}
but //do something is executed even if $x is 400
I noticed that this works:
if($x=="100"||$x=="200"||$x=="300")
{
//do something
}
How is the first block of code different from the second block of code? What am I doing wrong?
The reason why your code isn't working is because the result of the expression:
('100' || '200' || '300')
is always TRUE because the expression contains at least one truthy value.
So, the RHS of the expression is TRUE, while the LHS is a truthy value, therefore the entire expression evaluates to TRUE. The reason why this is happening is because of the == operator, which does loose comparison. If you used ===, the resulting expression would always be FALSE. (unless of course the value of $x is false-y.)
Let's analyze this:
Assuming $x equal '400':
($x == ('100'||'200'||'300'))
// ^ ^
// true true
Make sense now?
Bottom line here is: This is the wrong way of comparing 3 values against a common variable.
My suggestion is that you use in_array:
if(in_array($x, array('100', '200', '300')) {
//do something...
}
you can take all values in array it is working Perfectly.
$x=400;
if(in_array($x, array('100', '200', '300'))) {
echo $x.'is in array';
} else {
echo $x.'is not in array';
}
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.