PHP If Else

The if and else statements are how a PHP script makes decisions. Instead of running every line of code every time, your program can check a condition and choose a different path depending on whether that condition is true or false. Almost every real-world script — validating a form, checking a user’s login, deciding what to show on a page — relies on conditional branching, which makes if/else one of the most important building blocks in the language.

Overview: How PHP If/Else Works

An if statement evaluates an expression and converts the result to a boolean (true or false) using PHP’s rules of "truthiness." If the expression is truthy, the block of code attached to the if runs. If it is falsy, PHP either skips it, checks an elseif condition, or falls through to an else block if one exists.

Internally, when the Zend Engine (PHP’s runtime) compiles your script, an if statement becomes a conditional jump in the compiled opcodes. PHP evaluates the condition expression, coerces the resulting zval (Zend’s internal value container) to a boolean using the same rules as an explicit (bool) cast, and then jumps either into the if body or past it to the next elseif/else/end of the statement. Only one branch of an if/elseif/else chain ever executes — as soon as PHP finds a condition that evaluates to true, it runs that block and skips the rest of the chain entirely.

What counts as "falsy"?

Knowing PHP’s truthiness rules is essential, because they decide which branch runs. The following values are all considered falsy: the boolean false, the integer 0 and float 0.0, the empty string "" and the string "0", an empty array [], and null. Every other value — including the string "0.0", non-empty strings, and non-empty arrays — is truthy. This trips up a lot of beginners, especially the fact that the string "0" is falsy while "0.0" is not.

Syntax

if (condition1) {
    // runs if condition1 is true
} elseif (condition2) {
    // runs if condition1 is false and condition2 is true
} else {
    // runs if none of the above conditions are true
}
Part Description
if (condition) Required. Evaluates an expression; if it is truthy, the following block runs.
elseif (condition) Optional, repeatable. Checked only if every prior condition in the chain was false. You may also write it as two words, else if, when using curly-brace syntax.
else Optional, must be last. Runs when no prior condition matched. Takes no condition.
{ } Curly braces group multiple statements into one block. Technically optional for single-statement bodies, but strongly recommended (see Common Mistakes).

PHP also supports an alternative syntax using colons and endif;, which is popular in templates that mix HTML and PHP:

<?php $loggedIn = true; ?>
<?php if ($loggedIn): ?>
<p>Welcome back!</p>
<?php else: ?>
<p>Please log in.</p>
<?php endif; ?>

Output:

<p>Welcome back!</p>

Because $loggedIn is true, only the HTML between if and else is emitted; the HTML between else and endif is skipped entirely, not just left un-executed. This alternative syntax has no braces to forget, which is why many template files favor it.

Examples

Example 1: A basic if/else

<?php
$age = 20;

if ($age >= 18) {
    echo "You are eligible to vote.";
} else {
    echo "You are not eligible to vote yet.";
}

Output:

You are eligible to vote.

PHP evaluates $age >= 18, gets true, and runs the if block. The else block is skipped because a matching branch was already found.

Example 2: An elseif ladder

<?php
function getGrade(int $score): string
{
    if ($score >= 90) {
        return 'A';
    } elseif ($score >= 80) {
        return 'B';
    } elseif ($score >= 70) {
        return 'C';
    } elseif ($score >= 60) {
        return 'D';
    } else {
        return 'F';
    }
}

echo "Score 85 => Grade " . getGrade(85) . "\n";
echo "Score 55 => Grade " . getGrade(55) . "\n";

Output:

Score 85 => Grade B
Score 55 => Grade F

Each elseif is only checked if every condition above it was false, and conditions are tested top to bottom. For 85, PHP checks >= 90 (false), then >= 80 (true) and stops there — it never even evaluates >= 70. Order matters: if the ranges were written smallest-first, every score of 60+ would incorrectly return 'D' first.

Example 3: Nested if with logical operators

<?php
$user = [
    'isActive' => true,
    'role' => 'editor',
];

if ($user['isActive']) {
    if ($user['role'] === 'admin' || $user['role'] === 'editor') {
        echo "Access granted: dashboard unlocked.";
    } else {
        echo "Access denied: insufficient role.";
    }
} else {
    echo "Access denied: account is inactive.";
}

Output:

Access granted: dashboard unlocked.

Nested if statements let you check one condition only after another has already passed. Here, the role check only happens for active users at all — an inactive editor never reaches the inner if. This could also be written with a single condition using &&, but nesting is often clearer when each level represents a genuinely separate concern (account status vs. permission level).

How It Works Step by Step (Under the Hood)

  • 1. Parse. PHP’s parser reads the if/elseif/else chain and compiles it into a sequence of conditional jump opcodes for the Zend VM.
  • 2. Evaluate. At runtime, PHP evaluates the first condition expression. This can involve function calls, comparisons, and type juggling — all of that happens before the boolean conversion.
  • 3. Coerce to boolean. The resulting value is converted to true or false using PHP’s truthiness rules, exactly as if you wrote (bool) $expression.
  • 4. Branch or fall through. If the result is true, the VM jumps into that block and, after running it, jumps past the entire rest of the chain (skipping any remaining elseif/else). If false, it jumps to the next condition check, or to else, or past the whole statement if nothing matched and there is no else.
  • 5. Continue. Execution resumes with whatever statement follows the entire if/elseif/else chain, regardless of which branch ran.

Because only one branch ever executes, an if/elseif chain behaves differently from a series of independent if statements. Independent ifs are each evaluated regardless of what happened before, so more than one block can run; a chained elseif stops at the first match.

Common Mistakes

Mistake 1: Using = instead of ==

<?php
$status = false;

if ($status = true) {
    echo "Status is active.";
} else {
    echo "Status is inactive.";
}

Output:

Status is active.

This is syntactically valid PHP, which is exactly what makes it dangerous: $status = true is an assignment, not a comparison. It sets $status to true and the assignment expression itself evaluates to true, so the if always runs its true branch no matter what $status held before. The fix is to use == (loose equality) or, better, === (strict equality, which also checks the type):

<?php
$status = false;

if ($status === true) {
    echo "Status is active.";
} else {
    echo "Status is inactive.";
}

Output:

Status is inactive.

Mistake 2: Forgetting curly braces

<?php
$isAdmin = false;

if ($isAdmin)
    echo "Welcome, admin.";
    echo "Full access granted.";

Output:

Full access granted.

Without braces, only the single statement immediately after if belongs to it — indentation is just visual, PHP ignores it. Here, only echo "Welcome, admin."; is conditional; the second echo runs unconditionally every time, which is almost never what the author intended. Always wrap multi-line (and, arguably, even single-line) bodies in braces:

<?php
$isAdmin = false;

if ($isAdmin) {
    echo "Welcome, admin.";
    echo "Full access granted.";
} else {
    echo "Access denied.";
}

Output:

Access denied.

Best Practices

  • Always use curly braces, even for one-line bodies — it prevents the "dangling statement" bug from Mistake 2 and makes future edits safe.
  • Use === and !== by default instead of ==/!= to avoid surprising type-juggling results, and reserve loose comparison for cases where you deliberately want type coercion.
  • Put the condition variable on the left and the constant on the right (if ($role === 'admin')) — this reads naturally and, unlike some other languages, PHP does not require the reverse to guard against accidental assignment, but it still keeps intent clear.
  • Avoid deeply nested if statements; consider early returns ("guard clauses") to flatten logic, e.g. if (!$user) { return; } followed by the main logic un-nested.
  • For chains that compare one variable against many discrete values, consider a match expression (PHP 8+) instead of a long elseif ladder — it is stricter (uses ===), has no fall-through, and returns a value directly.
  • Order elseif conditions carefully when ranges overlap; put the most specific or most restrictive condition first.
  • Use the alternative if: ... else: ... endif; syntax inside HTML templates for readability, and the brace syntax everywhere else.

Practice Exercises

  • Exercise 1: Write a script that stores a number in a variable and uses if/elseif/else to print whether it is positive, negative, or zero.
  • Exercise 2: Write a function checkLogin(string $username, string $password) that uses nested if statements to check the username against "admin" and the password against "secret123" separately, printing a distinct message for "wrong username", "wrong password", and "success".
  • Exercise 3: Take the grading elseif ladder from Example 2 and rewrite it as a PHP 8 match expression using range checks with match (true). Compare the two versions — which is easier to read?

Summary

  • if runs a block only when its condition is truthy; elseif and else extend the chain, and only the first matching branch executes.
  • PHP converts conditions to boolean using truthiness rules — 0, "", "0", [], and null are falsy; almost everything else is truthy.
  • Curly braces define what belongs to each branch; omitting them for multi-statement bodies is a classic source of bugs.
  • Using = instead of ==/=== inside a condition is valid syntax but a logic bug, since it performs an assignment rather than a comparison.
  • The alternative colon syntax (if: ... elseif: ... else: ... endif;) is useful for mixing PHP with HTML in templates.
  • For long chains comparing one value against many options, a match expression is often clearer and safer than a long elseif ladder.