Booleans & Truthiness
The bool type has only two possible values, true and false, and on the surface that seems like the simplest type PHP has. The subtlety is not the type itself, but the rules PHP uses to decide whether some other type — a string, a number, an array — should count as true or false when it shows up in a boolean context such as an if statement. Those rules are called truthiness, and PHP's specific list of exceptions is a well-known source of bugs if you have not memorized it.
The literal bool values
true and false
<?php $isLoggedIn = true; $hasPermission = false; var_dump($isLoggedIn); var_dump($hasPermission); var_dump($isLoggedIn && $hasPermission); var_dump($isLoggedIn || $hasPermission);
bool(true) bool(false) bool(false) bool(true)
true and false are keywords and are case-insensitive (TRUE and False both work), though writing them lowercase is the near-universal convention in modern PHP code.
The falsy values
When any non-boolean value is used where a boolean is expected, PHP converts it using a short, fixed list of "falsy" values. Everything that is not on this list converts to true. Memorizing this list is genuinely worth doing, because it is short and it is the source of nearly every truthiness surprise in PHP.
The integer
0and the float0.0(and-0.0).The empty string
"".The string
"0"— but no other numeric string, e.g."0.0"and"00"are both truthy.An empty array
[].null.
Checking each falsy value
<?php
$falsyCandidates = [0, 0.0, "", "0", [], null];
foreach ($falsyCandidates as $candidate) {
echo var_export($candidate, true) . ' is ' . ($candidate ? 'truthy' : 'falsy') . "\n";
}0 is falsy 0.0 is falsy '' is falsy '0' is falsy array ( ) is falsy NULL is falsy
The surprising truthy cases
Two values in particular catch people off guard because they look like they "should" be falsy by analogy with "0", but PHP treats them as truthy: the string "0.0" and a string containing just a space, " ".
'0.0' and ' ' are truthy
<?php var_dump((bool) "0.0"); // bool(true) - only the exact string "0" is falsy var_dump((bool) " "); // bool(true) - a space is a non-empty string var_dump((bool) "0"); // bool(false) var_dump((bool) "false"); // bool(true) - the word "false" is just a non-empty string!
bool(true) bool(true) bool(false) bool(true)
The falsy-values table
Value | Truthy or falsy? |
|---|---|
| Falsy |
| Falsy |
| Falsy |
| Falsy |
| Falsy |
| Falsy |
| Truthy |
| Truthy |
| Truthy |
| Truthy (a non-empty array, even of falsy values) |
The classic string-"0" comparison bug
A frequent real-world bug comes from strpos(), which returns the integer position where a substring was found, or false if it was not found at all. If the substring is found at position 0 — the very start of the string — a loose truthiness check treats that success as if it were a failure, because 0 is falsy.
The strpos() pitfall
<?php
$sentence = "PHP is fun";
if (strpos($sentence, "PHP")) {
echo "Found it!";
} else {
echo "Not found."; // this branch runs, even though "PHP" IS in the string!
}Not found.
strpos($sentence, "PHP") actually returns 0, because "PHP" starts at index 0 — but if (0) is falsy, so the wrong branch executes. The fix is to compare against false explicitly with the strict !== operator, rather than relying on truthiness.
The correct, strict fix
<?php
$sentence = "PHP is fun";
if (strpos($sentence, "PHP") !== false) {
echo "Found it!";
} else {
echo "Not found.";
}Found it!
Converting explicitly with (bool)
Explicit boolean casting
<?php var_dump((bool) "yes"); // bool(true) - any non-empty, non-"0" string var_dump((bool) 3.14); // bool(true) - any non-zero number var_dump((bool) [0, 0]); // bool(true) - non-empty array, contents don't matter
bool(true) bool(true) bool(true)