Control Flow

Reviewed & published by Brayan K

By the end of this lesson you'll make your PHP make decisions — branching with if, choosing between many options with switch and the safer PHP 8 match, and writing tidy one-liners with the ternary and template if: ... endif; syntax.

Part of the free PHP course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ if / elseif / else

An if statement runs a block of code only when its condition is true. A condition is any expression that's true or false — usually a comparison like $score >= 70. Add elseif branches to test more conditions, and a final else as the catch-all. PHP checks them top to bottom and runs only the first block that's true, then skips the rest — so order matters. You can join conditions with && (both must be true) and || (either is enough).

<?php
// if / elseif / else — PHP runs the FIRST block whose condition is true,
// then skips the rest. Conditions use comparison operators like >= and == .

$score = 78;
echo "Student score: $score\n";

if ($score >= 90) {
    echo "Grade: A\n";           // skipped: 78 is not >= 90
} elseif ($score >= 80) {
    echo "Grade: B\n";           // skipped: 78 is not >= 80
} elseif ($score >= 70) {
    echo "Grade: C\n";           // ✅ true! 78 >= 70 — this runs, rest skipped
} else {
    echo "Grade: F\n";           // the catch-all when nothing above matched
}

// Combine conditions with && (AND) and || (OR).
$isWeekend = true;
$temperature = 28;

if ($isWeekend && $temperature > 25) {   // BOTH must be true
    echo "Beach day!\n";
} elseif ($isWeekend || $temperature > 30) {  // EITHER is enough
    echo "Day off, but cool\n";
} else {
    echo "A normal day\n";
}
?>

Note that PHP spells it elseif as one word (else if as two words also works). Because only the first true branch runs, the score 78 prints "Grade: C" and never even checks the lower branches.

2️⃣ switch / case / break / default

When you're comparing one value against a list of fixed options, a long if/elseif chain gets noisy. A switch reads better: you name the value once, then list each possible case. The crucial part is break — it tells PHP to stop once a case has run. Leave it out and PHP "falls through" into the next case and keeps going. default is the catch-all (like else), and you can stack cases to share one block.

<?php
// switch — compare ONE value against many fixed options.
// Each 'case' is a possible value; 'break' stops PHP falling into the next case.

$day = 3;  // 1 = Monday ... 7 = Sunday
echo "Day number: $day\n";

switch ($day) {
    case 1:
        echo "Monday\n";
        break;                 // stop here — don't run case 2
    case 6:
    case 7:                    // stacked cases: 6 OR 7 run the same block
        echo "Weekend!\n";
        break;
    default:                   // runs when no case matched (here: 2,3,4,5)
        echo "A weekday\n";   // ✅ $day is 3, so this runs
        // no break needed on the LAST case, but it's tidy to add one
}
?>

3️⃣ The PHP 8 match Expression

match (added in PHP 8) is a sharper switch. Three things make it nicer: it returns a value you can assign straight to a variable; it needs no break because it never falls through; and it compares with strict ===, so the integer 200 won't accidentally match the string "200". Each arm is value => result, arms are separated by commas, and one arm can list several values. Prefer match over switch for simple value-to-value mapping in PHP 8+.

<?php
// match (PHP 8) — like switch, but it RETURNS a value and uses strict
// comparison (===), so 200 only matches the integer 200, never "200".
// No 'break' needed, and commas separate the arms.

$httpCode = 404;

$message = match ($httpCode) {
    200, 201 => "Success",          // one arm can list several values
    301, 302 => "Redirect",
    404      => "Not Found",        // ✅ matches — this value is returned
    500      => "Server Error",
    default  => "Unknown",          // used if nothing else matched
};

echo "HTTP $httpCode: $message\n";   // the returned value lands in $message
?>

4️⃣ Ternary ? : and Null-Coalescing ??

When a choice is small, a full if/else is overkill. The ternary operator packs it into one line that produces a value: condition ? ifTrue : ifFalse. Closely related is null coalescing ??, which says "use the left value, or this fallback if the left is null or unset" — perfect for safe defaults like a guest name when no one is logged in. Keep ternaries to genuinely simple choices; nesting them quickly becomes unreadable.

<?php
// Ternary  condition ? valueIfTrue : valueIfFalse  — a one-line if/else
// that produces a VALUE. Great for picking between two options.

$age = 20;
$status = ($age >= 18) ? "Adult" : "Minor";   // 20 >= 18 → "Adult"
echo "Status: $status\n";

// ?? is the 'null coalescing' operator: "use the left value, OR this
// fallback if the left is null / not set". Handy for safe defaults.
$username = null;
$display = $username ?? "Guest";              // $username is null → "Guest"
echo "Welcome, $display\n";
?>

5️⃣ Alternative if: ... endif; Syntax

PHP offers a second way to write control structures: drop the curly braces, put a colon after the condition, and close with an endif; keyword (there's also endswitch;, endwhile;, and so on). It behaves exactly like the brace version. Its purpose is readability in templates — when you weave PHP through chunks of HTML, a matching endif; is far easier to spot than a lonely } buried in markup.

<?php
// Alternative syntax: swap the { } braces for a colon and an 'end...' keyword.
// It reads cleanly when you weave PHP through HTML in a template.
$loggedIn = true;
?>
<?php if ($loggedIn): ?>
    <p>Welcome back!</p>
<?php else: ?>
    <p>Please log in.</p>
<?php endif; ?>

Because $loggedIn is true, only the first block's HTML is sent; the else markup is skipped entirely.

6️⃣ Your Turn — Fill in the Blanks

Time to practise. Each script below is almost complete — replace every ___ using the 👉 hint, then run it and check it against the Output panel.

<?php
// 🎯 YOUR TURN — finish the if/elseif/else, then run it.
// Pick the band the temperature falls into.

$temp = 30;

if ($temp >= 30) {
    echo ___;                  // 👉  "Hot\n"
} elseif (___) {               // 👉 condition for 20 or above:  $temp >= 20
    echo "Warm\n";
} else {
    echo "Cool\n";
}

// ✅ Expected output (with $temp = 30):
//    Hot
?>

Now a match. Fill in the missing result and the catch-all keyword so it returns the right label.

<?php
// 🎯 YOUR TURN — complete this match so it returns the right label.
// Remember: match uses  value => result  arms and needs a default.

$grade = "B";

$label = match ($grade) {
    "A" => "Excellent",
    "B" => ___,                // 👉  "Good"
    "C" => "Okay",
    ___ => "Unknown grade",    // 👉 the catch-all keyword:  default
};

echo "Grade $grade: $label\n";

// ✅ Expected output:
//    Grade B: Good
?>

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Control Flow

StructureExampleUse When
if / elseif / elseif ($n > 0) { ... }Different conditions to test, in order
switchswitch ($x) { case 1: ... break; }One value vs many fixed options
matchmatch ($x) { 1 => "a", default => "b" }Map a value to a value (PHP 8+, strict)
? :$ok ? "yes" : "no"A simple one-line either/or value
??$name ?? "Guest"A default when the value is null/unset
if: ... endif;if ($ok): ?> ... <?php endif;Mixing PHP with HTML in templates

Mini-Challenge: Ticket Price

No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments. This is exactly the decide-run-check loop you'll use on every real script.

<?php
// 🎯 MINI-CHALLENGE: a tiny ticket-price calculator.
// No code is filled in — work from the steps, then run it.
//
// 1. Set  $age  to a number (try 12).
// 2. Use if/elseif/else to choose a price:
//      under 5        → "Free"
//      5 to 17        → "Child: $8"
//      18 and over    → "Adult: $15"
// 3. echo the result on its own line.
//
// Tip: order matters — test the smallest range first, or use ranges
//      like ($age >= 5 && $age <= 17).
//
// ✅ Expected output (with $age = 12):
//    Child: $8

// your code here
?>

🎉 Lesson Complete!

Practice quiz

In an if / elseif / else chain, how many blocks run?

  • Every block whose condition is true
  • Always the else block
  • Only the FIRST block whose condition is true
  • All of them in order

Answer: Only the FIRST block whose condition is true. PHP runs only the first block whose condition is true, then skips the rest.

What keyword stops a switch from 'falling through' into the next case?

  • break
  • stop
  • exit
  • end

Answer: break. break ends a case; without it PHP keeps running into the following case.

Which comparison does the PHP 8 match expression use?

  • Loose ==
  • <=> spaceship
  • It depends on the value
  • Strict ===

Answer: Strict ===. match always compares with strict ===, so 200 never matches the string "200".

What happens if match has no matching arm and no default?

  • It returns null
  • It throws an UnhandledMatchError
  • It returns false
  • It runs the first arm

Answer: It throws an UnhandledMatchError. match throws an UnhandledMatchError rather than silently doing nothing.

Which is a key advantage of match over switch?

  • It returns a value you can assign
  • It needs more break statements
  • It uses loose comparison
  • It only works with strings

Answer: It returns a value you can assign. match returns a value, needs no break, and compares strictly.

What does the ternary ($age >= 18) ? "Adult" : "Minor" produce when $age is 20?

  • "Minor"
  • true
  • "Adult"
  • 20

Answer: "Adult". 20 >= 18 is true, so the ternary returns the value before the colon: "Adult".

What does $display = $username ?? "Guest" give when $username is null?

  • null
  • "Guest"
  • An error
  • false

Answer: "Guest". ?? falls back to "Guest" because $username is null.

How does PHP spell the keyword for an additional condition?

  • else if only
  • elif
  • otherwise
  • elseif (one word; else if also works)

Answer: elseif (one word; else if also works). PHP spells it elseif as one word, though 'else if' as two words also works.

What is the alternative if: ... endif; syntax mainly for?

  • Faster execution
  • Readability inside HTML templates
  • Avoiding semicolons
  • Defining functions

Answer: Readability inside HTML templates. It replaces braces with a colon and endif; making PHP-in-HTML templates easier to read.

Why can you stack cases like 'case 6: case 7:' in a switch?

  • To run different code for each
  • It is a syntax error
  • So 6 OR 7 run the same shared block
  • To compare strictly

Answer: So 6 OR 7 run the same shared block. Stacked cases share one block, so both values trigger the same code.

Continue this course

Frequently asked questions

When should I use match instead of switch in PHP?

Reach for match (PHP 8+) whenever you are picking a value from a fixed set of options. It is shorter, needs no break statements, compares strictly with === so 200 never matches the string "200", and it returns a value you can assign straight to a variable. Use switch when you need to run several statements per branch or you are targeting PHP 7, where match does not exist.

What is the difference between == and === in conditions?

== compares values after PHP converts types for you, so 0 == "0" and even 0 == "" can surprise you. === compares value AND type, so "5" === 5 is false. Prefer === in your if conditions: it is predictable and avoids the loose-comparison traps that bite beginners. match() always uses === for you.

Why does my switch run more than one case?

You almost certainly forgot a break. Without break, PHP keeps running the next case's code too — called fall-through. Sometimes that is intentional (stacking case 6: case 7: to share a block), but usually it is a bug. Put a break at the end of every case, or switch to match(), which never falls through.

What happens if match has no matching arm and no default?

PHP throws an UnhandledMatchError and stops. Unlike switch, match refuses to silently do nothing — it forces you to handle every case. Add a default => arm to catch anything you did not list, exactly like the else on an if. This strictness is a feature: it surfaces values you forgot to handle.

What is the if: ... endif; syntax for?

It is the alternative syntax: replace the { } braces with a colon after the condition and an endif; (or endswitch;, endwhile;) keyword to close. It behaves identically to the brace version. Its purpose is readability inside HTML templates, where opening and closing PHP tags around lots of markup makes stray braces easy to lose.