Logical Operators
Logical operators combine boolean expressions into more complex conditions: "is the user logged in and an admin?", "is the value empty or negative?". PHP offers two spellings for the same three core operations — symbolic (&&, ||) and word-based (and, or) — and they are not perfectly interchangeable. Knowing why is one of the more important gotchas in the language.
AND, OR, and NOT
&& evaluates to true only when both sides are true. || evaluates to true when at least one side is true. ! flips a boolean: true becomes false and vice versa.
&&, ||, and !
<?php $age = 20; $hasTicket = true; var_dump($age >= 18 && $hasTicket); // bool(true) var_dump($age >= 65 || $hasTicket); // bool(true) var_dump(!$hasTicket); // bool(false)
bool(true) bool(true) bool(false)
xor
xor (exclusive or) returns true when exactly one side is true — if both sides are true or both are false, it returns false. It has no symbolic equivalent in PHP.
xor
<?php var_dump(true xor false); // bool(true) - exactly one is true var_dump(true xor true); // bool(false) - both true var_dump(false xor false); // bool(false) - both false
bool(true) bool(false) bool(false)
Short-circuit evaluation
Both &&/and and ||/or are short-circuiting: PHP stops evaluating as soon as the overall result is already determined. For &&, if the left side is false, the right side is never evaluated because the whole expression must be false regardless. For ||, if the left side is true, the right side is skipped. This is not just an optimization — it is commonly relied on to avoid errors.
Short-circuiting avoids an error
<?php
$user = null;
// Safe: if $user is falsy, the property access on the right never runs
if ($user && $user->isActive()) {
echo "Active user";
} else {
echo "No active user";
}No active user
Had PHP evaluated both sides unconditionally, $user->isActive()
on a null value would raise a fatal error. Short-circuiting is
exactly what makes this common defensive pattern work.
The precedence trap: and/or vs &&/||
This is the classic PHP interview question, and it is a genuine, documented gotcha rather than trivia. && and || have higher precedence than = (assignment), which is what you would expect. But and and or have lower precedence than =. That difference means swapping && for and in an assignment can silently change what gets stored in your variable.
The and/&& assignment trap
<?php $result = true && false; var_dump($result); // bool(false) - as expected $result = true and false; var_dump($result); // bool(true) - surprising!
bool(false) bool(true)
In the second line, because = binds tighter than and, PHP parses it as ($result = true) and false — the assignment happens first with just true, and the and false part is evaluated but its result is thrown away. This is almost never the intent, and it is exactly why the symbolic operators are the safer default.
Operator | Meaning | Precedence vs = |
|---|---|---|
| Logical AND | Higher than = |
| Logical OR | Higher than = |
| Logical NOT | Higher than = |
| Logical AND | Lower than = |
| Logical OR | Lower than = |
| Logical exclusive OR | Lower than = |
&&/||bind tighter than=;and/orbind looser than=.Both forms short-circuit: the right side is skipped once the result is already known.
xoris true only when exactly one operand is true.Short-circuiting is commonly used to guard against calling a method on
null.