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: true and false.
  • 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 the boolval() 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 false on failure (like strpos()), always check with === false / !== false, never a plain if (!$result).
  • Declare bool return 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 $canEdit rather than ambiguous ones like $flag or $status.
  • Avoid comparing booleans to true/false literals in conditions (if ($isValid === true)); just write if ($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): bool that returns true when $n is even. Test it against 0, 7, and -4, printing the boolean result for each using var_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 produces true or false. 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|false returns a discount percentage (which could legitimately be 0) or false if the code is invalid. Write the calling code that correctly distinguishes “valid code, 0% discount” from “invalid code” using strict comparison.

Summary

  • PHP’s bool type has exactly two values, true and false, 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, and null. 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 0 or "") alongside a false failure signal must be checked with strict comparison to avoid misclassifying valid results as failures.