4、流程控制(上):if-else判断、switch-case分支、匹配表达式(match)

写代码说白了就是让计算机做决策。你告诉它:「如果这样,就做A;否则,就做B。」这就是流程控制。今天咱们聊聊PHP里最常用的三种决策工具:if-elseswitch-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(连写),但我觉得分开写更清晰。你在项目里保持一致就好。

小技巧:判断顺序很重要!从最严格的条件开始写。比如先判断 >= 90,再判断 >= 80。如果你反过来,先判断 >= 60,那85分就直接输出「及格」了,后面的判断根本不会执行。

4.1.2 三元运算符:if-else的简写

有时候判断逻辑很简单,比如根据用户是否登录显示不同内容。写一整段if-else有点啰嗦,这时候可以用三元运算符。

<?php
$isLoggedIn = true;
$message = $isLoggedIn ? "欢迎回来" : "请登录";
echo $message; // 输出:欢迎回来
?>

格式是:条件 ? 真值 : 假值。说白了就是一行搞定if-else。但别滥用,嵌套太多层会让代码很难读。我在项目中见过有人写了三层三元运算符嵌套,维护的时候简直想骂人。

避坑指南:我曾经在项目里用三元运算符判断用户权限,结果忘了加括号,导致逻辑完全错了。记住:复杂判断老老实实用if-else,别为了省几行代码给自己挖坑。

4.2 switch-case:多值匹配的利器

当你要判断一个变量的多个具体值时,switch-caseif-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结构整齐,一眼就能看出所有可能的情况。

重要提醒: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。

小技巧:利用穿透特性可以简化代码。但一定要加注释说明,不然别人看代码会一脸懵:「这里是不是忘了写break?」

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链更紧凑,而且有返回值。

注意:match必须处理所有可能的情况。如果某个值没有匹配到任何分支,而且没有default,会抛出UnhandledMatchError错误。所以最好总是加上default分支。

4.4 实战建议:怎么选?

说了这么多,到底什么时候用哪个?我总结一下我的经验:

  • if-else:判断范围、复杂条件、只有两三个分支。最灵活,最常用。
  • switch-case:判断多个具体值,而且需要穿透特性。老项目里常见。
  • match:PHP 8+项目首选。简洁、安全、有返回值。新项目我基本都用它。

你想想看,写代码不只是让机器能跑,更要让人能看懂。选择合适的流程控制语句,代码的可读性会提升一大截。我个人习惯是:能用match的地方绝不用switch,能用switch的地方尽量不用if-else链。

核心总结:流程控制是程序的骨架。if-else是基础,switch-case是多值匹配的老将,match是PHP 8带来的新秀。掌握它们,你就能让代码按照你的意愿执行。下一节我们会聊循环控制,到时候你会看到这些判断语句和循环配合起来有多强大。