刚接触PHP的时候,大多数人写的条件判断都是if和else if的组合。当分支只有两三个时没什么问题,可一旦要判断的情况多起来,比如把一个分数映射成五个等级,if else就会越写越长,缩进也越来越深,后期维护相当费劲。PHP提供了switch语句来专门处理这种多分支场景,结构清晰,写法接近自然语言,是初学者必须掌握的流程控制基础。本文将从基本语法、实例演练到常见的坑点,完整讲清楚switch语句该怎么写。

一、switch语句的基本语法结构
switch语句的核心思想是:拿一个表达式的值,依次和后面每个case的值做比较,哪个匹配就执行哪个分支的代码。它的完整写法如下:
<?php
switch (表达式) {
case 值1:
// 表达式等于值1时执行
break;
case 值2:
// 表达式等于值2时执行
break;
default:
// 所有case都不匹配时执行
break;
}
?>这段结构里有四个关键点需要理解。switch后面括号里是要判断的表达式,通常是一个变量;case后面跟要比较的值,注意是值不是表达式判断,所以写case $x > 60:是错误用法;break用来结束整个switch语句的执行,如果省略它会继续往下执行下一个case的代码;default相当于else,前面的case全部不匹配时才会走到这里,通常放在最后作为兜底逻辑。
还有一个细节容易忽略:case后面比较用的是松散比较(==),不是严格比较(===)。这意味着字符串"1"和数字1会被认为是相等的。如果对类型要求严格,要么在使用switch前先做类型转换,要么改用match表达式(PHP 8.0新增),match使用的是严格比较。另外,case语句本身只负责标记入口,冒号后面可以写任意多行代码,直到遇到break或switch结构结束为止。
二、两个典型实例:成绩分级与星期判断
先看一个最经典的成绩等级判断。需求是:90分以上为优秀,80到89为良好,70到79为中等,60到69为及格,60以下为不及格。switch不擅长范围判断,但可以配合取整技巧来实现:
<?php
$score = 85;
// 利用intdiv取十位数,把范围判断转成具体值判断
switch (intdiv($score, 10)) {
case 10:
case 9:
echo "优秀";
break;
case 8:
echo "良好";
break;
case 7:
echo "中等";
break;
case 6:
echo "及格";
break;
default:
echo "不及格";
}
?>注意上面代码里case 10后面故意没写break,直接跟了case 9,这叫case的合并写法。因为满分100分和90多分都属于优秀,让100的情况自然落到case 9的代码块里执行即可。这种“不写break继续往下走”的特性用好了能简化代码,用不好就是灾难,后面坑点部分会详细说。
再看一个直接匹配具体值的例子,根据数字输出星期几:
<?php
$day = 3;
switch ($day) {
case 1:
echo "星期一";
break;
case 2:
echo "星期二";
break;
case 3:
echo "星期三";
break;
case 4:
echo "星期四";
break;
case 5:
echo "星期五";
break;
case 6:
case 7:
echo "周末";
break;
default:
echo "非法输入";
}
?>这种场景下switch的优势非常明显。如果用if else写,要连续写七个else if,而switch把每个可能值平铺出来,一眼就能看清所有分支。同时别忘了default分支,它除了兜底,还承担了参数校验的作用,比如用户传了0或者8,就能被default拦截并给出提示。
三、初学者最容易踩的三个坑
第一个坑是忘记写break。前面说过,switch匹配到某个case后会一直往下执行,直到遇到break。来看一段有问题的代码:
<?php
$level = "A";
switch ($level) {
case "A":
echo "优秀";
case "B":
echo "良好"; // 会意外执行
case "C":
echo "中等"; // 也会意外执行
break;
default:
echo "未知";
}
// 输出:优秀良好中等
?>本意是输出“优秀”,结果三个echo全部执行了。这种行为在PHP官方文档里叫fall-through(贯穿执行)。解决办法很直接:每个case的代码块末尾都老老实实写上break,哪怕你觉得肯定不会贯穿。如果确实需要贯穿(比如前面成绩分级的合并case),建议加一行注释说明是有意为之,方便后来的维护者看懂意图。
第二个坑是松散比较导致的意外匹配。因为case用的是==比较,字符串和数字比较时会做类型转换。比如switch ("abc")在老版本PHP里和case 0:是匹配的,因为"abc"转换成数字是0,这种问题排查起来非常隐蔽。升级到PHP 8之后这个行为有了调整,但最稳妥的做法依然是保证switch的表达式和case的值类型一致,或者在入口处用is_int、is_string之类的函数先做类型检查。
第三个坑是分号和冒号用混。case后面必须用冒号,写成case 1;会直接报语法错误。同样,switch结构体的大括号也不能省略(除非使用另一种冒号语法switch (...): ... endswitch;,这种写法在模板文件里偶尔能见到,初学阶段先掌握大括号写法即可)。此外,default虽然习惯上写在最后,但语法上它也可以写在任意位置,只要记得它也需要break,否则同样会贯穿到后面的case。
四、switch与if else、match该怎么选
三种写法各有适用场景。判断条件是同一个变量的多个具体取值时,switch最合适,结构清晰且执行效率略高,因为PHP引擎可以用跳转表直接定位分支,而if else需要逐个条件求值。判断条件是范围、大小比较或者多个不同变量组合时,if else更灵活。而PHP 8引入的match表达式适合简短的单值返回场景:
<?php
$code = 404;
// match是表达式,有返回值,使用严格比较,不需要break
$message = match (true) {
$code >= 500 => "服务器错误",
$code >= 400 => "客户端错误",
$code >= 200 => "请求成功",
default => "未知状态码",
};
echo $message; // 输出:客户端错误
?>match还有两个特点值得注意:没有匹配项且不写default时会抛出错误而不是像switch那样静默跳过,这能在编译期暴露逻辑漏洞;它天然不会贯穿,省去了break的烦恼。不过match只能用于PHP 8.0及以上版本,初学者在学习阶段建议先把switch的语法和坑点吃透,因为在大量现存项目和面试题里,switch依然是考察重点。掌握的原则很简单:固定值多分支用switch,复杂条件用if else,新项目里简短映射用match,三者组合起来就能应对绝大多数流程控制需求。
php switch语句PHP流程控制switch case用法修改时间:2026-09-09 18:31:02