PHP Switch
switch's loose comparison trap, fallthrough, and PHP 8's match expression.
基本用法
<?php
$color = "blue";
switch ($color) {
case "red":
echo "红色\n";
break;
case "blue":
case "cyan":
echo "蓝色系\n";
break;
default:
echo "未知\n";
}蓝色系To share a block across cases, leave earlier cases empty so execution falls through — the only legitimate use of fallthrough.
忘记 break 的后果
<?php
$n = 2;
switch ($n) {
case 1:
echo "一\n";
case 2:
echo "二\n";
case 3:
echo "三\n";
break;
default:
echo "其它\n";
}二
三case 2 it keeps running case 3. Such bugs are nearly invisible in review — **every case needs break or return** unless fallthrough is intentional.松散比较的坑
<?php
switch ("1abc") {
case 1:
echo "命中 1\n";
break;
default:
echo "未命中\n";
}未命中Before PHP 8, "1abc" == 1 was true and this matched case 1. PHP 8 compares a non-numeric string with a number as strings, so it no longer matches.
switch always uses ==, never ===. For strict matching use match (PHP 8) or an if / elseif chain.match 表达式
PHP 8's match is an expression with a return value, compares strictly, and must be exhaustive (otherwise UnhandledMatchError).
<?php
$color = "blue";
$msg = match ($color) {
"red" => "红色",
"blue", "cyan" => "蓝色系",
default => "未知",
};
echo $msg, "\n";
// 严格比较:0 和 "0" 不是同一个分支
$v = 0;
echo match ($v) {
0 => "整数零",
"0" => "字符串零",
}, "\n";
// 分支可以写表达式
$score = 85;
$grade = match (true) {
$score >= 90 => "A",
$score >= 80 => "B",
default => "C",
};
echo $grade, "\n";蓝色系
整数零
B| Feature | switch | match |
|---|---|---|
| Is an expression | 否(语句) | 是,有返回值 |
| Comparison | 松散 == | 严格 === |
| Fallthrough | 会 | 不会 |
| Must be exhaustive | 否,可省略 default | 是,否则抛错 |
| Multiple values | 多个 case 堆叠 | 逗号分隔 |
In new code match largely replaces switch. No need to rewrite old code, but prefer match for new branching logic.
基本用法
<?php
$color = "blue";
switch ($color) {
case "red":
echo "红色\n";
break;
case "blue":
case "cyan":
echo "蓝色系\n";
break;
default:
echo "未知\n";
}蓝色系多个 case 共用一段代码时,前面的 case 后面什么都不写,让执行「贯穿」下去。这是 switch 唯一正当的贯穿用法。
忘记 break 的后果
<?php
$n = 2;
switch ($n) {
case 1:
echo "一\n";
case 2:
echo "二\n";
case 3:
echo "三\n";
break;
default:
echo "其它\n";
}二
三case 2 后没有 break,继续执行 case 3 的代码。这类 bug 在 code review 里极难看出来——**每个 case 都要有 break 或 return**,除非你明确要贯穿。松散比较的坑
<?php
switch ("1abc") {
case 1:
echo "命中 1\n";
break;
default:
echo "未命中\n";
}未命中PHP 8 之前 "1abc" == 1 为 true(字符串被转成数字 1),这个 switch 会命中 case 1。PHP 8 改成「非数字字符串与数字比较时按字符串比」,才变成 未命中。
switch 永远是 == 不是 ===。需要严格匹配就用 match(PHP 8)或者 if / elseif 链。match 表达式
PHP 8 引入的 match 是表达式,有返回值,用严格比较,且必须穷尽所有分支(否则抛 UnhandledMatchError)。
<?php
$color = "blue";
$msg = match ($color) {
"red" => "红色",
"blue", "cyan" => "蓝色系",
default => "未知",
};
echo $msg, "\n";
// 严格比较:0 和 "0" 不是同一个分支
$v = 0;
echo match ($v) {
0 => "整数零",
"0" => "字符串零",
}, "\n";
// 分支可以写表达式
$score = 85;
$grade = match (true) {
$score >= 90 => "A",
$score >= 80 => "B",
default => "C",
};
echo $grade, "\n";蓝色系
整数零
B| 对比项 | switch | match |
|---|---|---|
| 是表达式 | 否(语句) | 是,有返回值 |
| 比较方式 | 松散 == | 严格 === |
| 贯穿 | 会 | 不会 |
| 必须穷尽 | 否,可省略 default | 是,否则抛错 |
| 多值匹配 | 多个 case 堆叠 | 逗号分隔 |
新项目里,match 基本可以替代 switch。老代码不必急着改,但新写分支逻辑优先用 match。