PHP Switch

JA JASWANT Updated 16 Oct 2026
8 min read ·Lesson 2 of 248

What Is the switch Statement?

In simple terms: switch compares one value against a list of possible values and runs the code for the one that matches. It is an organized alternative to a long chain of if...elseif statements that all test the same variable.

Technically: switch evaluates an expression once, then compares the result with each case value using loose comparison (==). Execution starts at the first matching case and continues until a break statement (or the end of the switch) is reached.

Why It Exists

Code like this repeats the same variable in every condition:

if ($status === 'pending') { ... }
elseif ($status === 'paid') { ... }
elseif ($status === 'shipped') { ... }
elseif ($status === 'delivered') { ... }
else { ... }

switch names the value once and lists the possible cases, which is easier to scan when there are many options.


Syntax

switch (expression) {
    case value1:
        // code for value1
        break;
    case value2:
        // code for value2
        break;
    default:
        // code when no case matches
}
PartMeaning
switch (expression)The value to compare, evaluated once
case value:A value to compare against; execution starts here when it matches
break;Leaves the switch
default:Runs when no case matches (optional)

Example

<?php
$status = 'shipped';

switch ($status) {
    case 'pending':
        echo "Awaiting payment\n";
        break;
    case 'paid':
        echo "Payment received, preparing your order\n";
        break;
    case 'shipped':
        echo "Your order is on the way\n";
        break;
    case 'delivered':
        echo "Delivered. Enjoy your purchase!\n";
        break;
    default:
        echo "Unknown order status\n";
}

Output

Your order is on the way

How It Works

  1. $status is evaluated once: 'shipped'.
  2. PHP compares it with each case value from top to bottom: 'pending', 'paid', then 'shipped', which matches.
  3. Execution starts at case 'shipped': and runs its statements.
  4. break ends the switch, so the remaining cases are not executed.
  5. If no case had matched, the default block would run.

The Role of break: Fall-Through

What Happens Without break

case labels only mark where execution starts. Without a break, PHP continues running the statements of the following cases — this is called fall-through.

<?php
$status = 'pending';

switch ($status) {
    case 'pending':
        echo "Awaiting payment\n";
    case 'paid':
        echo "Payment received\n";
        break;
    case 'shipped':
        echo "On the way\n";
        break;
}

Output

Awaiting payment
Payment received

The pending case is missing its break, so execution "falls through" into the paid case and prints a message that is wrong for a pending order. Forgetting break is the most common switch bug.

Intentional Fall-Through: Grouping Cases

Fall-through is useful when several values should run the same code. Stack the case labels without statements between them:

<?php
function dayType(string $day): string
{
    switch ($day) {
        case 'Sat':
        case 'Sun':
            return 'Weekend';
        case 'Fri':
            return 'Almost the weekend';
        default:
            return 'Weekday';
    }
}

foreach (['Mon', 'Fri', 'Sun'] as $day) {
    echo "$day: " . dayType($day) . "\n";
}

Output

Mon: Weekday
Fri: Almost the weekend
Sun: Weekend
  • 'Sat' and 'Sun' share one block.
  • Inside a function, return leaves both the switch and the function, so no break is needed after it.

When fall-through is intentional in a case that does contain statements, add a comment such as // no break so readers know it is deliberate.


The default Case

  • default runs when no case matches.
  • It is optional, but including it is recommended — it handles unexpected values explicitly instead of silently doing nothing.
  • It can appear anywhere in the list, but it is conventionally placed last.
  • A switch can have only one default.
<?php
$paymentMethod = 'crypto';

switch ($paymentMethod) {
    case 'card':
    case 'upi':
    case 'netbanking':
        echo "Redirecting to payment gateway...\n";
        break;
    case 'cod':
        echo "Cash on delivery selected\n";
        break;
    default:
        echo "Payment method '$paymentMethod' is not supported\n";
}

Output

Payment method 'crypto' is not supported

switch Uses Loose Comparison

switch compares with ==, so type juggling applies (see PHP Type Juggling):

<?php
$input = '1e1';

switch ($input) {
    case '10':
        echo "Matched '10'\n";
        break;
    default:
        echo "No match\n";
}

$flag = '0';

switch ($flag) {
    case false:
        echo "Matched false\n";
        break;
    case '0':
        echo "Matched '0'\n";
        break;
}

Output

Matched '10'
Matched false
  • '1e1' == '10' is true because both strings are numeric and equal to 10.
  • '0' == false is true, so the first matching case is false, not '0'.

For exact matching, normalize the value's type before the switch (for example, cast to int or compare only strings), or use match, which compares strictly.


switch (true) for Range Conditions

A case can contain any expression. Switching on true runs the first case whose expression is true:

<?php
$score = 82;

switch (true) {
    case $score >= 90:
        $grade = 'A';
        break;
    case $score >= 75:
        $grade = 'B';
        break;
    case $score >= 60:
        $grade = 'C';
        break;
    default:
        $grade = 'F';
}

echo "Grade: $grade\n";

Output

Grade: B

This works, but if...elseif or match (true) expresses range checks more directly. You will see switch (true) in older code.


Multiple Statements in a Case

Each case can contain as many statements as needed, which is one advantage switch has over match:

<?php
function handleCommand(string $command, array &$cart): string
{
    switch ($command) {
        case 'add':
            $cart[] = 'item-' . (count($cart) + 1);
            $message = 'Item added';
            break;

        case 'remove':
            if ($cart === []) {
                return 'Cart is already empty';
            }
            array_pop($cart);
            $message = 'Item removed';
            break;

        case 'clear':
            $cart = [];
            $message = 'Cart cleared';
            break;

        default:
            return "Unknown command: $command";
    }

    return "$message. Cart has " . count($cart) . " item(s).";
}

$cart = [];

foreach (['add', 'add', 'remove', 'checkout', 'clear', 'remove'] as $command) {
    echo handleCommand($command, $cart) . "\n";
}

Output

Item added. Cart has 1 item(s).
Item added. Cart has 2 item(s).
Item removed. Cart has 1 item(s).
Unknown command: checkout
Cart cleared. Cart has 0 item(s).
Cart is already empty

How It Works

  • array &$cart passes the cart by reference, so the function can modify the caller's array (see Pass by Reference).
  • Each case updates the cart, sets a message, and breaks to the shared return at the end.
  • The remove case contains its own if, showing that cases can hold any logic.
  • Unknown commands and the empty-cart situation return early.

switch Inside Loops: break and continue

Inside a switch, break exits the switch, not the surrounding loop. To exit the loop from inside a switch, use break 2; to skip to the next loop iteration, use continue 2.

<?php
$lines = ['INFO start', 'SKIP debug', 'ERROR disk full', 'INFO end'];

foreach ($lines as $line) {
    $level = strtok($line, ' ');

    switch ($level) {
        case 'SKIP':
            continue 2;          // next line in the foreach
        case 'ERROR':
            echo "Stopping: $line\n";
            break 2;             // leave the foreach completely
        default:
            echo "Logged: $line\n";
    }

    echo "  (processed)\n";
}

Output

Logged: INFO start
  (processed)
Stopping: ERROR disk full

How It Works

  • strtok($line, ' ') returns the first word of the line.
  • continue 2 skips the rest of the current foreach iteration, so (processed) is not printed for the SKIP line.
  • break 2 exits both the switch and the foreach, so INFO end is never processed.

A plain continue inside a switch behaves like break (it targets the switch), and since PHP 7.3 PHP warns about it at compile time: "continue" targeting switch is equivalent to "break". Use continue 2 when you mean the loop.


switch vs if...elseif vs match

Featureif...elseifswitchmatch (PHP 8.0+)
ComparesAny conditionsOne value against casesOne value against arms
ComparisonWhatever you writeLoose (==)Strict (===)
Fall-throughNoYes, unless breakNo
Returns a valueNoNoYes
Multiple statements per branchYesYesNo (one expression per arm)
No matchNothing happens (unless else)Nothing happens (unless default)Throws UnhandledMatchError

Guidelines:

  • Use match when you are choosing a value based on one input and want strict, safe comparison.
  • Use switch when each case must run several statements, or when you maintain code that already uses it.
  • Use if...elseif for unrelated conditions or complex ranges.

Same Logic With match

<?php
function fileCategory(string $filename): string
{
    return match (strtolower(pathinfo($filename, PATHINFO_EXTENSION))) {
        'jpg', 'jpeg', 'png', 'webp' => 'Image',
        'pdf' => 'PDF document',
        'doc', 'docx' => 'Word document',
        'zip', 'rar' => 'Archive',
        default => 'Other',
    };
}

foreach (['photo.JPG', 'resume.pdf', 'notes.docx', 'backup.zip', 'script.php'] as $file) {
    echo "$file: " . fileCategory($file) . "\n";
}

Output

photo.JPG: Image
resume.pdf: PDF document
notes.docx: Word document
backup.zip: Archive
script.php: Other

The equivalent switch would need a case line per extension, a break after each group, and a variable to hold the result. match lists several values per arm with commas and returns the result directly.


Common Mistakes

Forgetting break

Effect: Execution falls through into the next case.

Fix: End every case with break (or return inside functions), and comment any intentional fall-through.

Relying on Loose Comparison

Effect: '0' matches case false; numeric strings match unexpected cases.

Fix: Normalize types first, or use match.

Using continue Instead of continue 2 in Loops

Effect: continue acts like break for the switch; the rest of the loop body still runs.

Fix: continue 2 (or break 2 to leave the loop).

Omitting default

Effect: Unexpected values are silently ignored, and variables assigned in the cases may remain undefined.

Fix: Always include default, even if it only logs or throws an error.

Duplicate Case Values

Effect: Only the first matching case runs; the duplicate is unreachable.

Fix: Keep case values unique.


Best Practices

  • End every case with break or return, and comment intentional fall-through.
  • Group cases that share behavior by stacking case labels.
  • Always include a default branch.
  • Normalize the switch value's type to avoid loose-comparison surprises.
  • Prefer match for value selection in PHP 8 code; use switch when cases need multiple statements.

Official reference: https://www.php.net/manual/en/control-structures.switch.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings Function Arguments PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer PHP Form Handling PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro PHP Class Constants Encryption with Sodium Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Variables Scope Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS What Is `$_SERVER` ? $_REQUEST $_POST $_GET $_FILES $_COOKIE PHP Type Juggling MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes PSR-4 Autoloading Installing Extensions (PECL / PIE) OPcache & Performance PHP-FPM Project: Contact Form with Email Project: Login & Registration System Project: CRUD App with MySQL Project: Shopping Cart with Sessions Project: REST API with PHP DateTime Class Timezones PHP Include Include vs Require PHP File Handling PHP File Open/Read PHP File Create/Write File Delete / Rename / Copy PHP Directories PHP CSV Files
Ask about this post
AI Ask about this post

Ask questions about PHP Switch and get answers drawn from it.

Signed-in readers only.