tags:

views:

181

answers:

8

PHP's "or" is an interesting keyword. In fact it's so interesting that sometimes I just don't get it. Here's 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)

Wouldn't you expect the last echo to also print 1? If not - why?

+20  A: 

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

Pekka
I would have written it as `$foo = (0 or 1);`
Treffynnon
@Trefynnon: No, `or` has lower precedence than `=`. If you were to use `||` you would be right though.
nico
@Treffynnon: But that would be a different statement.
You
@Pekka: Brilliant! Makes perfect sense now.
Emanuil
@nico and @you I don't see how that is any different to the `$foo = 0 || 1;` that Pekka has now updated his answer with. They both return boolean responses. Wrapping the or statement in brackets causes it to be evaluated before it is assigned to $foo.
Treffynnon
@Trefynnon: No, they're different, because the operator priority is `or < = < ||`. So, when you write `$foo = 0 or 1` the `=` is considered before the `or` (`=` has higher priority than `or`). When you write `$foo = 0 || 1` the `||` has higher priority than `=` and therefore is interpreted before it.
nico
@Treffynnon: You are right that `$foo = (0 or 1) === $foo = 0 || 1` . But `$foo = 0 or 1 === ($foo = 0) or 1`.
Felix Kling
Guys that is my point I am not trying to explain why the original code is broken (`$foo = 0 or 1;` === `($foo = 0) or 1;`) I am proposing a fix (`$foo = (0 or 1);`) without losing the `or` operator which I personally find easier to read in code, but yes you do need to remain aware of the differing precedence with `||` when using it. Sorry if that was not clear.
Treffynnon
@Treffynnon makes sense now! That's a fine and valid workaround, no doubt.
Pekka
+4  A: 

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.

Giu
+5  A: 

No, I wouldn't, that's because of operator precedance:

 $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 = 

 // there this is 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.
nikic
A: 

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.

You
A: 

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.

cHao
A: 

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

Stephen
A: 

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.

Brian Hooper
A: 

Here's what's exactly happening in each of your examples:

echo 0 or 1;

is evaluated as

echo (0 or 1);

or takes precedence over the echo language construct.


$foo = (0 or 1);

is evaluated as is. Anything in parentheses takes precedence depending on the level of nesting of parentheses. In this case, 0 or 1 is evaluated first, which results in 1, which is then assigned to $foo.


$foo = 0 or 1;

is evaluated as

($foo = 0) or 1;

Here, variable assignment (with the = operator) takes precedence over or. The assignment statement has a value of 0, which evaluates to false, so PHP looks at the next condition, which is 1. The 1 is completely irrelevant to the assignment of $foo, which is now 0.

BoltClock