Logical Operators and Short-Circuiting
&& and || evaluate lazily; that laziness is a feature you can design with. Plus the and/or precedence trap.
Logical operators short-circuit: PHP stops as soon as the answer is certain. In $a && $b, if $a is false, $b is never evaluated. That is not just an optimisation — it's how you guard expensive or unsafe calls.
Easy example
<?php
$user = null;
// safe: the right side only runs if $user is truthy
if ($user && $user->isAdmin()) {
echo "admin";
} else {
echo "not admin";
}The and / or trap
PHP also has the words and and or, but they bind looser than =. So $ok = true and false; assigns true to $ok (surprise!). Stick to && and || unless you know exactly why you want the word forms.
Example
When to use it
- Short-circuit a database query by checking a cached value with && so the query only runs on cache miss.
- Use || to log a warning and return a default when an optional config value is missing.
- Avoid the and/or precedence trap by always using && and || in boolean expressions with assignments.
More examples
Short-circuit to skip expensive work
The || short-circuits: if $user is already truthy the right side never executes, skipping the DB call.
<?php
$cache = [];
function fetchUser(int $id): array {
echo "DB query for $id\n";
return ['id' => $id, 'name' => 'Alice'];
}
$id = 1;
$user = $cache[$id] ?? null;
$user || ($user = fetchUser($id));
echo $user['name']; // DB query runs only oncePrecedence trap: and vs &&
'and' and 'or' have lower precedence than assignment; always use && and || to avoid this subtle trap.
<?php
$a = true && false; // $a = (true && false) = false
$b = true and false; // ($b = true) and false => $b is true!
var_dump($a); // bool(false)
var_dump($b); // bool(true) — assignment binds tighter than 'and'Lazy guard with &&
The ctype_xdigit check only runs when the length is already correct, saving a character-scan on obviously bad input.
<?php
function isValidToken(string $t): bool {
return strlen($t) === 32 && ctype_xdigit($t);
}
echo isValidToken('abc') ? 'valid' : 'invalid'; // invalid
echo isValidToken(str_repeat('a', 32)) ? 'valid' : 'invalid'; // valid
Discussion