4、流程控制(上):if-else判断、switch-case分支、匹配表达式(match)
写代码说白了就是让计算机做决策。你告诉它:「如果这样,就做A;否则,就做B。」这就是流程控制。今天咱们聊聊PHP里最常用的三种决策工具:if-else、switch-case,还有PHP 8才有的新家伙——match表达式。
4.1 if-else:最基础的条件判断
if-else是每个程序员最早接触的判断语句。它的逻辑很简单:条件成立,执行一段代码;不成立,执行另一段。
<?php
$score = 85;
if ($score >= 60) {
echo "及格了,不错!";
} else {
echo "没及格,继续加油。";
}
?>
嗯,这里要注意:if后面的条件必须用括号括起来。我刚开始学的时候老忘记,结果报错半天找不到原因。
4.1.1 多分支:else if
有时候判断不止两种情况。比如成绩等级:90分以上是优秀,80分以上是良好,60分以上是及格,否则是不及格。这时候就需要else if。
<?php
$score = 85;
if ($score >= 90) {
echo "优秀";
} else if ($score >= 80) {
echo "良好";
} else if ($score >= 60) {
echo "及格";
} else {
echo "不及格";
}
?>
我个人习惯把else if写成两个单词,虽然PHP也支持elseif(连写),但我觉得分开写更清晰。你在项目里保持一致就好。
4.1.2 三元运算符:if-else的简写
有时候判断逻辑很简单,比如根据用户是否登录显示不同内容。写一整段if-else有点啰嗦,这时候可以用三元运算符。
<?php
$isLoggedIn = true;
$message = $isLoggedIn ? "欢迎回来" : "请登录";
echo $message; // 输出:欢迎回来
?>
格式是:条件 ? 真值 : 假值。说白了就是一行搞定if-else。但别滥用,嵌套太多层会让代码很难读。我在项目中见过有人写了三层三元运算符嵌套,维护的时候简直想骂人。
4.2 switch-case:多值匹配的利器
当你要判断一个变量的多个具体值时,switch-case比if-else更清晰。比如根据星期几显示不同的活动安排。
<?php
$day = "周一";
switch ($day) {
case "周一":
echo "开会";
break;
case "周二":
echo "写代码";
break;
case "周三":
echo "代码评审";
break;
default:
echo "自由安排";
}
?>
这里有个关键点:每个case后面都要加break,否则会继续执行下一个case。这叫「穿透」——有时候是特性,有时候是bug。
4.2.1 什么时候用switch-case?
我个人经验是:当判断条件超过3个,而且都是具体的值(不是范围),用switch-case更合适。比如状态码处理、菜单选择、权限等级判断。
你想想看,如果用if-else写5个以上的分支,代码会变得又长又丑。而switch-case结构整齐,一眼就能看出所有可能的情况。
case "1" 能匹配到数字1。如果你需要严格比较,可以用match表达式(下面会讲)。
4.2.2 多个case共享同一段代码
有时候多个值对应同一个处理逻辑。比如周末两天都休息。
<?php
$day = "周六";
switch ($day) {
case "周六":
case "周日":
echo "休息日";
break;
default:
echo "工作日";
}
?>
这里case "周六"后面没有break,所以会直接穿透到case "周日",然后执行echo "休息日"。这是故意利用穿透特性,不是bug。
4.3 match表达式:PHP 8的优雅新选择
PHP 8引入的match表达式,说白了就是switch-case的升级版。它更简洁、更安全、更强大。
<?php
$day = "周一";
$activity = match ($day) {
"周一" => "开会",
"周二" => "写代码",
"周三" => "代码评审",
"周四", "周五" => "项目推进",
default => "自由安排",
};
echo $activity; // 输出:开会
?>
看到区别了吗?match用=>箭头,而且不需要break。每个分支默认只执行一个,不会穿透。它还会返回一个值,可以直接赋值给变量。
4.3.1 match vs switch:到底强在哪?
| 对比项 | switch-case | match |
|---|---|---|
| 返回值 | 没有返回值 | 有返回值 |
| 比较方式 | 松散比较(==) | 严格比较(===) |
| 穿透问题 | 需要break | 不会穿透 |
| 多个值匹配 | 利用穿透 | 逗号分隔 |
| 表达式支持 | 仅支持值 | 支持复杂表达式 |
举个例子,match的严格比较能避免很多隐式类型转换带来的坑。我曾经在项目里用switch判断状态码,结果"1"和1混在一起,排查了半天才发现是类型问题。换成match后,再也没出过这种问题。
4.3.2 match的进阶用法
match还可以处理更复杂的条件,比如结合函数调用。
<?php
$age = 25;
$category = match (true) {
$age < 18 => "未成年人",
$age >= 18 && $age < 60 => "成年人",
$age >= 60 => "老年人",
};
echo $category; // 输出:成年人
?>
这里match (true)是个小技巧。每个分支的条件是一个布尔表达式,匹配到第一个为true的分支就返回。这比if-else链更紧凑,而且有返回值。
default,会抛出UnhandledMatchError错误。所以最好总是加上default分支。
4.4 实战建议:怎么选?
说了这么多,到底什么时候用哪个?我总结一下我的经验:
- if-else:判断范围、复杂条件、只有两三个分支。最灵活,最常用。
- switch-case:判断多个具体值,而且需要穿透特性。老项目里常见。
- match:PHP 8+项目首选。简洁、安全、有返回值。新项目我基本都用它。
你想想看,写代码不只是让机器能跑,更要让人能看懂。选择合适的流程控制语句,代码的可读性会提升一大截。我个人习惯是:能用match的地方绝不用switch,能用switch的地方尽量不用if-else链。