Skip to main content

    Lesson 4 • Beginner

    Control Flow 🔀

    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.

    What You'll Learn in This Lesson

    • Branch with if / elseif / else and pick the first true block
    • Combine conditions with && (and) and || (or)
    • Match one value against many options with switch and break
    • Use the PHP 8 match expression — strict, and it returns a value
    • Write compact choices with the ternary ? : and null-coalescing ??
    • Use the alternative if: ... endif; syntax inside HTML templates

    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).

    if / elseif / else — grading and combining conditions
    <?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";
    }
    ?>
    Output
    Student score: 78
    Grade: C
    Beach day!
    This is real code — run it for free atonecompiler.com/phpor in your own editor.

    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.

    switch — one value, many cases
    <?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
    }
    ?>
    Output
    Day number: 3
    A weekday
    This is real code — run it for free atonecompiler.com/phpor in your own editor.

    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+.

    match — strict, returns a value
    <?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
    ?>
    Output
    HTTP 404: Not Found
    This is real code — run it for free atonecompiler.com/phpor in your own editor.

    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.

    Ternary and null-coalescing one-liners
    <?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";
    ?>
    Output
    Status: Adult
    Welcome, Guest
    This is real code — run it for free atonecompiler.com/phpor in your own editor.

    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.

    Template-friendly alternative syntax
    <?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; ?>
    Output
        <p>Welcome back!</p>
    This is real code — run it for free atonecompiler.com/phpor in your own editor.

    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.

    🎯 Your turn: finish the if/elseif
    <?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
    ?>
    Output
    Hot
    Fill the two ___ blanks — an echo value and a comparison condition. With $temp = 30 the output should be one line: Hot.

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

    🎯 Your turn: complete the match
    <?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
    ?>
    Output
    Grade B: Good
    Replace the first ___ with the result for "B", and the second with the catch-all keyword default. Output: Grade B: Good.

    Common Errors (and the fix)

    • A switch runs the wrong (or every) case — you forgot a break. Without it, PHP keeps running into the next case after a match ("fall-through"). Put a break; at the end of every case, or switch to match, which never falls through.
    • "UnhandledMatchError: Unhandled case" — your match had no arm for the value and no default. Unlike switch, match refuses to silently do nothing. Add a default => ... arm to catch anything you didn't list.
    • A comparison passes when it shouldn't — you used loose ==, which converts types first, so 0 == "hello" can be true in old PHP and "5" == 5 is true. Use strict === in conditions to compare value and type.
    • An if always runs, no matter the value — you wrote if ($x = 5) with one =. That assigns 5 to $x (a truthy result) instead of comparing. To compare, use two equals: if ($x == 5) (or ===).

    Pro Tips

    • 💡 Default to match for value-to-value mapping in PHP 8+ — no break, strict comparison, and it returns a value you can assign.
    • 💡 Always add a default to a match (and usually a switch) so unexpected values are handled, not crashing or silently ignored.
    • 💡 Use === in conditions. Strict comparison avoids PHP's loose-typing surprises and makes your intent obvious.
    • 💡 Keep ternaries simple. One ? : is readable; nested ternaries are not — reach for a full if/else instead.

    📋 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

    Frequently Asked Questions

    Q: 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.

    Q: 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.

    Q: 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.

    Q: 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.

    Q: 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.

    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.

    🎯 Mini-Challenge: pick a ticket price by age
    <?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
    ?>
    Use if/elseif/else to map an age to a price, then echo it. With $age = 12 the output should be a single line: Child: $8.

    🎉 Lesson Complete!

    • if / elseif / else runs the first true branch; combine conditions with && and ||
    • switch compares one value to many cases — and every case needs a break
    • match (PHP 8) returns a value, uses strict ===, and throws if nothing matches and there's no default
    • ✅ The ternary ? : and null-coalescing ?? give you compact one-liners
    • ✅ The alternative if: ... endif; syntax keeps PHP-in-HTML templates readable
    • ✅ Prefer === in conditions, and watch the single = assignment trap
    • Next lesson: Loops — repeat code with for, while, and foreach

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service