PHP Switch Statements
When you need to compare a single value against many possible matches, the
switch statement provides a cleaner alternative to multiple if-elseif
chains. PHP 8 also introduces the powerful match expression for even more concise code.
Basic Switch Statement
The switch statement evaluates an expression once and compares it against multiple cases:
<?php
switch (expression) {
case value1:
// Code for value1
break;
case value2:
// Code for value2
break;
default:
// Code if no match
}
?>
| Keyword | Purpose |
|---|---|
switch |
Starts the switch block with expression to evaluate |
case |
Defines a value to compare against |
break |
Exits the switch block (prevents fall-through) |
default |
Executes when no case matches (optional) |
Click Run to execute your code
Switch vs If-Elseif
Compare the same logic written both ways:
<?php
$color = "red";
// Using if-elseif (verbose)
if ($color === "red") {
echo "Stop!";
} elseif ($color === "yellow") {
echo "Caution!";
} elseif ($color === "green") {
echo "Go!";
} else {
echo "Unknown color";
}
// Using switch (cleaner for many cases)
switch ($color) {
case "red":
echo "Stop!";
break;
case "yellow":
echo "Caution!";
break;
case "green":
echo "Go!";
break;
default:
echo "Unknown color";
}
?>
Fall-Through Behavior
Without break, execution "falls through" to the next case. This can be intentional:
<?php
$month = 2;
switch ($month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
$days = 31;
break;
case 4:
case 6:
case 9:
case 11:
$days = 30;
break;
case 2:
$days = 28; // Simplified, ignoring leap years
break;
default:
$days = 0;
}
echo "Month $month has $days days.";
?>
break is a common bug! Always add break
unless you intentionally want fall-through behavior. Add a comment when fall-through is intentional.
Switch with Strings
Switch works with any scalar type, including strings:
<?php
$action = strtolower($_GET['action'] ?? 'view');
switch ($action) {
case 'create':
echo "Creating new record...";
break;
case 'read':
case 'view':
echo "Displaying record...";
break;
case 'update':
case 'edit':
echo "Editing record...";
break;
case 'delete':
echo "Deleting record...";
break;
default:
echo "Unknown action: $action";
}
?>
==), not strict
comparison. This means "0" will match 0. Use match (PHP 8+)
for strict comparison.
Alternative Syntax
Like if statements, switch has an alternative syntax for templates:
<?php $page = "about"; ?>
<?php switch ($page): ?>
<?php case "home": ?>
<h1>Welcome Home</h1>
<?php break; ?>
<?php case "about": ?>
<h1>About Us</h1>
<?php break; ?>
<?php case "contact": ?>
<h1>Contact Us</h1>
<?php break; ?>
<?php default: ?>
<h1>Page Not Found</h1>
<?php endswitch; ?>
PHP 8 Match Expression
PHP 8 introduced match, a more powerful and safer alternative to switch:
| Feature | switch | match (PHP 8+) |
|---|---|---|
| Returns value | No (statement) | Yes (expression) |
| Comparison type | Loose (==) |
Strict (===) |
| Requires break | Yes | No (implicit) |
| Fall-through | Possible | Not possible |
| No match handling | Continues silently | Throws UnhandledMatchError |
Click Run to execute your code
Match Syntax
Match is an expression that returns a value:
<?php
$role = "editor";
// Match returns a value directly
$permissions = match($role) {
"admin" => ["create", "read", "update", "delete", "manage"],
"editor" => ["create", "read", "update"],
"viewer" => ["read"],
default => []
};
print_r($permissions);
// Multiple values in one arm
$isWeekend = match($dayNumber) {
1, 2, 3, 4, 5 => false,
6, 7 => true,
default => throw new InvalidArgumentException("Invalid day")
};
?>
match over switch in PHP 8+ for:
- Cleaner, more concise code
- Type-safe strict comparisons
- No accidental fall-through bugs
- When you need to return a value
Common Mistakes
1. Forgetting break statements
<?php
$fruit = "apple";
// โ WRONG: Missing break causes fall-through!
switch ($fruit) {
case "apple":
echo "Red fruit\n"; // Executes
case "banana":
echo "Yellow fruit\n"; // Also executes!
case "grape":
echo "Purple fruit\n"; // Also executes!
}
// โ
CORRECT: Add break to each case
switch ($fruit) {
case "apple":
echo "Red fruit\n";
break;
case "banana":
echo "Yellow fruit\n";
break;
case "grape":
echo "Purple fruit\n";
break;
}
?>
2. Relying on loose comparison
<?php
$value = "0";
// โ WRONG: Loose comparison matches unexpectedly
switch ($value) {
case 0:
echo "Zero (integer)"; // This matches "0" string!
break;
case "0":
echo "Zero (string)"; // Never reached
break;
}
// โ
CORRECT: Use match for strict comparison (PHP 8+)
$result = match($value) {
0 => "Zero (integer)",
"0" => "Zero (string)", // This matches correctly
default => "Something else"
};
?>
3. No default case
<?php
$status = "archived";
// โ WRONG: No handling for unexpected values
switch ($status) {
case "active":
processActive();
break;
case "pending":
processPending();
break;
}
// "archived" silently does nothing!
// โ
CORRECT: Always include default
switch ($status) {
case "active":
processActive();
break;
case "pending":
processPending();
break;
default:
throw new Exception("Unknown status: $status");
}
?>
Exercise: HTTP Status Handler
Task: Create a function that returns an appropriate message and CSS class for HTTP status codes.
Requirements:
- Handle status codes: 200, 201, 301, 400, 401, 403, 404, 500
- Return an array with 'message' and 'class' keys
- Group similar codes (e.g., 2xx = success, 4xx = error)
- Handle unknown codes with a default
Show Solution
<?php
function getStatusInfo($code) {
// Using match for PHP 8+
return match($code) {
200 => ['message' => 'OK', 'class' => 'success'],
201 => ['message' => 'Created', 'class' => 'success'],
301 => ['message' => 'Moved Permanently', 'class' => 'redirect'],
400 => ['message' => 'Bad Request', 'class' => 'error'],
401 => ['message' => 'Unauthorized', 'class' => 'error'],
403 => ['message' => 'Forbidden', 'class' => 'error'],
404 => ['message' => 'Not Found', 'class' => 'error'],
500 => ['message' => 'Server Error', 'class' => 'error'],
default => ['message' => 'Unknown Status', 'class' => 'unknown']
};
}
// Test it
$codes = [200, 404, 500, 999];
foreach ($codes as $code) {
$info = getStatusInfo($code);
echo "$code: {$info['message']} ({$info['class']})\n";
}
?>
Summary
- switch: Compare one value against multiple cases
- case: Define each possible value to match
- break: Required to prevent fall-through (unless intentional)
- default: Handles unmatched values (always include it!)
- Fall-through: Multiple cases can share the same code block
- match (PHP 8+): Modern alternative with strict comparison and returns a value
- Comparison: switch uses
==, match uses===
What's Next?
Now that you can make decisions with if and switch, let's learn about While Loops - repeating code until a condition is no longer true!
Enjoying these tutorials?