PHP Booleans
A boolean is the simplest data type in PHP: it holds exactly one of two values, true or false. Booleans are the backbone of every decision your program makes — every if, while, and comparison ultimately reduces to one. Understanding exactly how PHP converts other values (numbers, strings, arrays, null) into booleans is one of the most important skills for avoiding subtle bugs in real code.
Overview: How Booleans Work
Internally, PHP represents every variable as a zval (Zend value) with a type tag. For booleans, that type is IS_TRUE or IS_FALSE — there is no separate storage for the words “true” or “false”; they are just distinct type tags with no associated data, which is why booleans are extremely cheap to store and compare. When you write true or false in source code, PHP treats these as case-insensitive keywords (TRUE, True, and true are identical), though lowercase is the near-universal style convention.
What makes booleans deceptively tricky is PHP’s type juggling: PHP is a weakly typed language, so almost any value can be implicitly or explicitly converted to a boolean. This happens constantly — every time a value is used as the condition of an if, while, for, or the ternary/null-coalescing-adjacent ?: shorthand, PHP silently converts it to a boolean behind the scenes using a fixed set of rules. Knowing those rules precisely (not just “empty stuff is false”) is what separates code that behaves correctly from code that has an off-by-one class of bug lurking in it.
The bool Type at a Glance
- Two possible values:
trueandfalse. - Type name returned by
gettype()is the string"boolean". - Type name used in type declarations (parameters, return types, properties) is
bool. - Casting is done with
(bool)or(boolean), or theboolval()function.
Syntax
$flag = true;
$flag = false;
$asCast = (bool) $someValue;
$asFunc = boolval($someValue);
$typeName = gettype($flag); // "boolean"
true/false— the two literal keywords, case-insensitive but conventionally lowercase.(bool)— explicit cast operator, converts any value to a boolean using PHP’s conversion rules.boolval($value)— a function form of the same cast, useful when you need to pass the conversion as a callable.bool— the type-hint keyword used in function signatures, e.g.function isActive(): bool.
Examples
Example 1: Declaring and Using Booleans
<?php
$isLoggedIn = true;
$hasPermission = false;
var_dump($isLoggedIn);
var_dump($hasPermission);
echo "Logged in: " . ($isLoggedIn ? "yes" : "no") . "\n";
echo "Has permission: " . ($hasPermission ? "yes" : "no") . "\n";
Output:
bool(true)
bool(false)
Logged in: yes
Has permission: no
This example shows the two literals in use and demonstrates that var_dump() prints booleans as bool(true) or bool(false) — useful for debugging, since echoing a boolean directly prints nothing for false and 1 for true.
Example 2: Truthy and Falsy Conversion Rules
<?php
$tests = [
'int 0' => 0,
'int 1' => 1,
'int -1' => -1,
'float 0.0' => 0.0,
'string "0"' => "0",
'empty string ""' => "",
'string "0.0"' => "0.0",
'string "false"' => "false",
'null' => null,
'empty array []' => [],
'array [0]' => [0],
];
foreach ($tests as $label => $value) {
$result = (bool) $value ? 'true' : 'false';
echo "{$label} => {$result}\n";
}
Output:
int 0 => false
int 1 => true
int -1 => true
float 0.0 => false
string "0" => false
empty string "" => false
string "0.0" => true
string "false" => true
null => false
empty array [] => false
array [0] => true
This is the table every PHP developer eventually memorizes the hard way. Notice two traps: the string "0.0" is truthy (only the single-character string "0" is falsy — every other non-empty string, including "false" and "0.0", is truthy), and any non-empty array is truthy regardless of its contents, even [0] which contains a falsy element.
Example 3: Booleans Driving Real Logic
<?php
function isValidAge(int $age): bool
{
return $age >= 18 && $age <= 120;
}
$ages = [15, 18, 45, 150];
foreach ($ages as $age) {
$valid = isValidAge($age);
$status = match (true) {
$valid => 'accepted',
default => 'rejected',
};
echo "Age {$age}: {$status}\n";
}
Output:
Age 15: rejected
Age 18: accepted
Age 45: accepted
Age 150: rejected
Here isValidAge() is declared with a bool return type, and the boolean it returns is fed into a match (true) expression — a common PHP 8 idiom for turning a boolean (or several conditions) into a readable branch selection.
Under the Hood: How PHP Converts Values to Boolean
When PHP needs a boolean (in an if condition, a (bool) cast, or a logical operator like &&), it applies these rules, checked by type:
| Type | Converts to false when… |
Otherwise |
|---|---|---|
| int / float | the value is exactly 0 or 0.0 |
true |
| string | the value is "" (empty) or the single character "0" |
true |
| array | the array has zero elements | true |
| null | always | never true |
| object | never (objects are always truthy) | always true |
Comparison operators add another layer: == (loose equality) type-juggles both operands before comparing, while === (strict equality) refuses to convert types at all — it checks both value and type. This is why 0 == false is true but 0 === false is false. As of PHP 8, comparisons between numeric strings and numbers were made saner (a non-numeric string like "abc" is no longer loosely equal to 0), but the safest habit is still to reach for ===/!== whenever you specifically care about a boolean result, not just “something falsy.”
Common Mistakes
Mistake 1: Confusing a Falsy Result with “Not Found”
<?php
$position = strpos("Hello world", "Hello");
if (!$position) {
echo "Not found\n";
} else {
echo "Found at position {$position}\n";
}
Output:
Not found
This is wrong. strpos() found "Hello" at position 0, but 0 is falsy, so !$position is true and the code incorrectly reports “not found.” The fix is to compare against false strictly, since strpos() only returns the boolean false when the substring is genuinely absent:
<?php
$position = strpos("Hello world", "Hello");
if ($position === false) {
echo "Not found\n";
} else {
echo "Found at position {$position}\n";
}
Output:
Found at position 0
Mistake 2: Testing a Truthy Return Value with === true
<?php
function findUser(array $users, string $name): array|false
{
foreach ($users as $user) {
if ($user['name'] === $name) {
return $user;
}
}
return false;
}
$users = [['name' => 'Ana'], ['name' => 'Bo']];
$result = findUser($users, 'Ana');
if ($result === true) {
echo "User found\n";
} else {
echo "User not found\n";
}
Output:
User not found
The function returns an array on success, not the literal boolean true, so $result === true is always false here even though a user was found. When a function’s success value can be any truthy non-boolean, compare against the failure sentinel instead:
<?php
function findUser(array $users, string $name): array|false
{
foreach ($users as $user) {
if ($user['name'] === $name) {
return $user;
}
}
return false;
}
$users = [['name' => 'Ana'], ['name' => 'Bo']];
$result = findUser($users, 'Ana');
if ($result !== false) {
echo "User found: {$result['name']}\n";
} else {
echo "User not found\n";
}
Output:
User found: Ana
Best Practices
- Prefer
===and!==over==/!=whenever you want a real boolean comparison, not a type-juggled one. - When a function can return either a meaningful value or
falseon failure (likestrpos()), always check with=== false/!== false, never a plainif (!$result). - Declare
boolreturn and parameter types on functions that represent yes/no decisions — it documents intent and lets PHP catch type errors early. - Give boolean variables affirmative, readable names such as
$isActive,$hasAccess, or$canEditrather than ambiguous ones like$flagor$status. - Avoid comparing booleans to
true/falseliterals in conditions (if ($isValid === true)); just writeif ($isValid). - Remember that every non-empty array and every object is truthy, regardless of its contents — test
count()or a specific property instead of relying on implicit truthiness when that distinction matters.
Practice Exercises
- Exercise 1: Write a function
isEven(int $n): boolthat returnstruewhen$nis even. Test it against0,7, and-4, printing the boolean result for each usingvar_dump(). - Exercise 2: Create an array of 6 mixed values (include at least one
0, one empty string, one non-empty string, and one empty array). Loop over it and print, for each value, whether(bool)casting it producestrueorfalse. Predict the output on paper first, then verify your reasoning matches the conversion rules table above. - Exercise 3: A function
findDiscount(array $rules, string $code): int|falsereturns a discount percentage (which could legitimately be0) orfalseif the code is invalid. Write the calling code that correctly distinguishes “valid code, 0% discount” from “invalid code” using strict comparison.
Summary
- PHP’s
booltype has exactly two values,trueandfalse, stored internally as a type tag with no extra data. - Any value can be converted to boolean via
(bool),boolval(), or implicitly inside conditions — this is called type juggling. - Falsy values are:
0,0.0,"", the string"0", empty arrays, andnull. Everything else, including"0.0"and non-empty arrays/objects, is truthy. - Use
===/!==when you need an exact boolean or failure-sentinel check, not just “truthy vs falsy.” - Functions that can return a legitimate falsy value (like
0or"") alongside afalsefailure signal must be checked with strict comparison to avoid misclassifying valid results as failures.
