当前位置:首页>php>PHP 流程控制速查:if/switch/循环/函数

PHP 流程控制速查:if/switch/循环/函数

  • 2026-10-11 05:37:18
PHP 流程控制速查:if/switch/循环/函数

资料在文章末尾

这是 PHP 入门系列的第三篇。前两篇讲完了变量、数据类型和运算符,代码还只会从头到尾顺次执行。这一篇解决两个问题:让代码能根据不同情况走不同分支,以及把重复的逻辑封装成可复用的函数。涉及 if/switch 条件判断、while/for/foreach 循环、break/continue 跳转、自定义函数、参数返回值、作用域、匿名函数和箭头函数。每个知识点都配可直接运行的代码,建议边看边敲。

一、为什么需要流程控制

到目前为止,我们写的代码都是从上到下逐行执行,没有分叉。但真实业务里,代码必须应对各种情况:用户登录没?年龄够不够?购物车是不是空的?这些都要靠条件判断来处理。需要重复执行某段逻辑时(比如处理一批数据),就用循环。把常用逻辑提取出来做成函数,代码就能像搭积木一样组合复用。

本篇的知识链路:条件判断 → switch 多分支 → 循环结构 → 循环控制 → 函数定义与调用 → 参数与返回值 → 作用域 → 匿名与箭头函数。

二、条件判断:if / else / elseif

2.1 if 语句

最简单的判断:条件为 true 就执行大括号里的代码,为 false 就跳过。

<?php$weather = "rain";if ($weather == "rain") {    echo "带上雨伞!";}?>

2.2 if...else 二选一

条件不满足时,执行 else 里的代码。

<?php$weather = "sunny";if ($weather == "rain") {    echo "带上雨伞!";} else {    echo "戴上帽子!";}?>

2.3 if...elseif...else 多条件

多个条件依次判断,遇到第一个满足的就执行,后面的不再判断。

<?php$temperature = 22;if ($temperature < 10) {    echo "穿羽绒服";} elseif ($temperature >= 10 && $temperature <= 20) {    echo "穿外套";} else {    echo "穿 T 恤";}?>

elseif 可以写多个,最后一个 else 可以省略。

2.4 嵌套 if

if 可以嵌套使用,但层级别太深,超过三层就该考虑重构了。

<?php$is_logged = true;$is_admin = true;if ($is_logged) {    if ($is_admin) {        echo "进入管理后台";    } else {        echo "进入用户中心";    }} else {    echo "请先登录";}?>

代码风格上建议遵循 PSR-12:if 后跟一个空格,大括号风格团队统一即可,缩进用 4 个空格。

2.5 模板里的替代语法

PHP 嵌入大量 HTML 时,用 if(): ... endif; 语法更清晰,避免大括号难以配对。

<?php if ($logged_in): ?>    <p>欢迎回来,<?= $username ?></p><?php else: ?>    <p>请<a href="login.php">登录</a></p><?php endif; ?>

<?= $var ?>是 <?php echo $var; ?>的简写,输出变量很方便。

三、switch 语句:多值匹配的另一种写法

当一个变量要和多个确定值比较时,switch 比一串 elseif 更清晰。

<?php$choice = 2;switch ($choice) {    case 1:        echo "你选择了可乐。";        break;    case 2:        echo "你选择了雪碧。";        break;    case 3:        echo "你选择了果汁。";        break;    default:        echo "无效选择!";        break;}?>

三个关键点:

• case 之间是松散比较(==),不区分类型

• 每个 case 末尾的 break 不能漏,否则会发生"穿透",继续执行下一个 case

• default 相当于 else,所有 case 都不匹配时执行

穿透不一定是 bug,有时可以故意利用。比如让多个 case 共用同一段代码:

<?php$day = "Wednesday";switch ($day) {    case "Friday":        echo "TGIF!";        break;    case "Wednesday":    case "Thursday":        echo "快到周末了!";        break;    default:        echo "普通工作日";}?>

Wednesday 和 Thursday 共用一段输出。判断变量是否等于某个具体值用 switch,涉及范围或逻辑运算用 if。

四、循环结构

4.1 while 循环

先判断条件,为 true 就执行循环体,执行完再判断,直到条件为 false 退出。条件一开始就是 false 的话,循环体一次都不执行。

<?php$hungry = 3; // 吃 3 口饱while ($hungry > 0) {    echo "吃一口饭。\n";    $hungry--;}echo "饱了!";?>

输出:吃一口饭。×3,最后输出"饱了!"。

4.2 do...while 循环

先执行一次循环体,再判断条件。即使条件一开始就不满足,也会执行一次。

<?php$energy = 0;do {    echo "玩了一把游戏。\n";    $energy--;} while ($energy > 0);?>

即使 $energy = 0,也会输出一次"玩了一把游戏。"。

4.3 for 循环

最常用的计数循环。语法:for (初始化; 条件; 每次循环后操作) { ... }

<?phpfor ($i = 1; $i <= 10; $i++) {    echo "俯卧撑第 $i 个\n";}?>

三个部分的作用:

• 初始化($i = 1):只执行一次

• 条件($i <= 10):每次循环前检查,为 false 就退出

• 每次循环后操作($i++):循环体执行完后执行

三个部分都能省略(但分号不能省),比如无限循环写成 for (;;) { ... }。

4.4 foreach 循环:遍历数组

foreach 专门用来遍历数组,有两种写法。

只取值:

<?php$fruits = ["苹果", "香蕉", "橘子"];foreach ($fruits as $fruit) {    echo "水果:$fruit\n";}?>

同时取键和值:

<?php$user = [    "name" => "张三",    "age"  => 25,    "city" => "上海"];foreach ($user as $key => $value) {    echo "$key: $value\n";}?>

foreach 也能遍历对象的公共属性,处理数据库结果集时用得非常多。

五、循环控制:break 与 continue

5.1 break:终止整个循环

找到目标就立刻退出循环,不再继续。

<?phpfor ($i = 1; $i <= 10; $i++) {    if ($i == 5) {        echo "找到钥匙,在第 $i 个房间!";        break;    }    echo "搜索第 $i 个房间...\n";}?>

输出搜索 1-4 房间,找到第 5 个后立即跳出,不再执行 6-10。

5.2 continue:跳过本次,继续下一次

不退出循环,只是跳过当前这一轮剩下的代码,直接进入下一轮。

<?phpfor ($i = 1; $i <= 5; $i++) {    if ($i == 3) {        echo "第 $i 个不合格,跳过。\n";        continue;    }    echo "第 $i 个产品合格,包装。\n";}?>

第 3 个被跳过,其余都正常处理。

5.3 break 和 continue 后面跟数字

break 2 可以跳出两层嵌套循环,continue 2 跳过外层循环的本次迭代。可读性差,实际项目里尽量少用。

六、函数:把重复逻辑封装起来

6.1 定义和调用

函数是一段可重复使用的代码块,给它一个名字,传入参数,它执行任务并可能返回结果。

<?phpfunction greet() {    echo "你好,欢迎!";}greet();  // 输出:你好,欢迎!?>

函数名推荐小写加下划线,见名知义。

6.2 带参数的函数

<?phpfunction greet($name) {    echo "你好,$name!";}greet("小明");   // 输出:你好,小明!greet("小红");   // 输出:你好,小红!?>

多个参数用逗号分隔。

6.3 返回值 return

函数可以返回计算结果。一旦执行 return,函数立即结束。没有 return 的函数默认返回 NULL。

<?phpfunction multiply($x, $y) {    return $x * $y;}$result = multiply(4, 5);echo $result;   // 20?>

6.4 参数默认值与可变参数

调用时不传该参数,就用默认值。带默认值的参数必须放在非默认参数后面。

<?phpfunction order($food, $drink = "水") {    echo "你点了 $food 和 $drink。";}order("汉堡", "可乐");  // 你点了汉堡和可乐。order("披萨");          // 你点了披萨和水。?>

可变参数(PHP 5.6+):用 ... 接收任意数量参数,会被打包成数组。

<?phpfunction sum(...$numbers) {    $total = 0;    foreach ($numbers as $n) {        $total += $n;    }    return $total;}echo sum(1, 2, 3, 4);  // 10?>

6.5 类型声明(PHP 7+)

可以给参数和返回值指定类型,提前拦截类型错误。

<?phpfunction divide(int $a, int $b): float {    return $a / $b;}echo divide(10, 3);  // 3.333...?>

默认情况下 PHP 会尝试自动转换类型("10" 转 10)。要严格检查,在文件首行加 declare(strict_types=1);。

<?phpdeclare(strict_types=1);function add(int $a, int $b): int {    return $a + $b;}add("10", 20);  // 报错!必须传整数类型?>

可声明的类型:int、float、string、bool、array、object、iterable、callable、类/接口名,PHP 8.0+ 还支持 mixed 和联合类型(int|string)。

七、变量作用域

7.1 局部与全局

函数内部定义的变量是局部变量,外部不可见。外部定义的全局变量,在函数内部默认也不可见。

<?php$global_var = "外面";function test() {    $local_var = "里面";    echo $local_var;   // 输出 "里面"    // echo $global_var; // 报错!Undefined variable}test();// echo $local_var;    // 报错!Undefined variable?>

7.2 global 关键字

函数内部要访问全局变量,用 global 关键字声明,或用 $GLOBALS 超全局数组。

<?php$name = "全局张三";function show() {    global $name;    echo $name;           // 输出 "全局张三"    $name = "被函数修改";}show();echo $name;  // 输出 "被函数修改"?>

实际项目中尽量别用全局变量,会让代码难以调试。需要外部数据时,通过参数传入函数。

7.3 静态变量 static

函数执行完,局部变量通常会被销毁。用 static 声明的变量,在多次调用之间会保留值,只在第一次调用时初始化。

<?phpfunction counter() {    static $count = 0;    $count++;    echo $count . " ";}counter();  // 1counter();  // 2counter();  // 3?>

八、匿名函数与箭头函数

8.1 匿名函数(闭包)

没有名字的函数,可以赋值给变量,也可以作为参数传给其他函数。

<?php$greet = function($name) {    echo "你好,$name!";};$greet("小明");  // 你好,小明!?>

匿名函数要使用外部变量,用 use 关键字引入。默认是传值,要修改外部变量用 use (&$var)。

<?php$msg = "欢迎";$greet = function($name) use ($msg) {    echo "$msg,$name!";};$greet("小红");  // 欢迎,小红!?>

8.2 箭头函数(PHP 7.4+)

更简洁的匿名函数写法,自动捕获外部变量(按值),只能写一个表达式,自动返回。

<?php$factor = 3;$multiply = fn($x) => $x * $factor;echo $multiply(5);  // 15?>

九、综合示例:学生成绩管理程序

把前面学的流程控制和函数整合起来,写一个完整的成绩管理小程序。功能包括:录入成绩、修改分数、删除学生、自动评级、计算平均分和极值、数据持久化(session 存储,刷新页面不丢)。

<?phpsession_start();// 初始化会话存储成绩数组,刷新页面数据不消失if (!isset($_SESSION['student_scores'])) {    $_SESSION['student_scores'] = [        "张三" => 92.5,        "李四" => 78.0,        "王五" => 85.5,        "赵六" => 61.0,        "孙七" => 45.5,    ];}$student_scores = $_SESSION['student_scores'];// 删除学生逻辑$msg = "";if (isset($_GET['delname'])) {    $delName = $_GET['delname'];    if (isset($student_scores[$delName])) {        unset($student_scores[$delName]);        $_SESSION['student_scores'] = $student_scores;        $msg = "已删除学生:{$delName}";    }    header("Location: ".$_SERVER['PHP_SELF']);    exit;}// 接收表单提交数据(新增/修改)$error = "";if ($_SERVER["REQUEST_METHOD"] === "POST") {    $name = trim($_POST['name'] ?? "");    $score = trim($_POST['score'] ?? "");    if ($name === "") {        $error = "姓名不能为空!";    } elseif (!is_numeric($score) || $score < 0 || $score > 100) {        $error = "分数必须是0~100之间的数字!";    } else {        // 同名覆盖 = 修改分数;新名字 = 新增学生        $student_scores[$name] = (float)$score;        $_SESSION['student_scores'] = $student_scores;        header("Location: ".$_SERVER['PHP_SELF']);        exit;    }}// 根据分数获取等级function getGrade(float $score): string {    if ($score >= 90) return "A";    elseif ($score >= 80) return "B";    elseif ($score >= 70) return "C";    elseif ($score >= 60) return "D";    else return "F";}// 计算平均分function average(array $scores): float {    $total = 0;    $count = 0;    foreach ($scores as $score) {        $total += $score;        $count++;    }    return $count > 0 ? $total / $count : 0.0;}$avg = average($student_scores);// 遍历找出最高分、最低分、对应学生$max_score = 0;$max_student = "";$min_score = 100;$min_student = "";foreach ($student_scores as $name => $score) {    if ($score > $max_score) {        $max_score = $score;        $max_student = $name;    }    if ($score < $min_score) {        $min_score = $score;        $min_student = $name;    }}?><!DOCTYPE html><html lang="zh-CN"><head>    <meta charset="UTF-8">    <title>学生成绩管理系统</title>    <style>        .wrap { width: 500px; margin: 30px auto; text-align: center; }        table { border-collapse: collapse; width: 480px; margin: 20px auto; }        th, td { border: 1px solid #999; padding: 8px 10px; text-align: center; }        th { background-color: #f5f5f5; }        .form-box { border: 1px solid #ccc; padding: 15px; width: 480px; margin: 0 auto 20px; }        .error { color: red; margin: 10px 0; }        .success { color: green; }        input { padding: 6px; margin: 5px; width: 160px; }        button { padding: 6px 16px; background: #007bff; color: white; border: none; cursor: pointer; }        .del-btn { background: #dc3545; padding: 4px 10px; color: #fff; text-decoration: none; font-size: 14px; }    </style></head><body>    <div class="wrap">        <h2>学生成绩管理系统</h2>        <?php if ($msg): ?>            <div class="success"><?php echo $msg; ?></div>        <?php endif; ?>        <div class="form-box">            <h3>新增/修改学生成绩</h3>            <?php if ($error): ?>                <div class="error"><?php echo $error; ?></div>            <?php endif; ?>            <form method="post" action="">                <label>学生姓名:                    <input type="text" name="name" placeholder="输入姓名,同名自动修改分数">                </label>                <br>                <label>考试分数:                    <input type="number" step="0.5" min="0" max="100" name="score" placeholder="0~100">                </label>                <br>                <button type="submit">提交保存</button>            </form>        </div>        <h3>======= 成绩报告 =======</h3>        <table>            <tr>                <th>姓名</th>                <th>分数</th>                <th>等级</th>                <th>操作</th>            </tr>            <?php foreach ($student_scores as $name => $score): ?>                <tr>                    <td><?php echo $name; ?></td>                    <td><?php echo $score; ?></td>                    <td><?php echo getGrade($score); ?></td>                    <td>                        <a class="del-btn" href="?delname=<?php echo urlencode($name); ?>" onclick="return confirm('确定删除该学生?')">删除</a>                    </td>                </tr>            <?php endforeach; ?>        </table>        <p>平均分:<?php echo number_format($avg, 2); ?></p>        <p>最高分:<?php echo $max_student; ?>(<?php echo $max_score; ?> 分)</p>        <p>最低分:<?php echo $min_student; ?>(<?php echo $min_score; ?> 分)</p>        <p>当前总人数:<?php echo count($student_scores); ?> 人</p>    </div></body></html>

9.1 代码核心点拆解

会话初始化

session_start();if (!isset($_SESSION['student_scores'])) {    $_SESSION['student_scores'] = [ /* 初始5名学生 */ ];}$student_scores = $_SESSION['student_scores'];

• session_start() 开启会话,浏览器会话期间数据临时保存,刷新页面不丢

• isset() 判断会话中是否已有成绩数组,没有就加载初始数据

• 关闭浏览器后会话销毁,数据清空(这是 session 的特性,不是 bug)

表单接收与校验

if ($_SERVER["REQUEST_METHOD"] === "POST") {    $name = trim($_POST['name'] ?? "");    $score = trim($_POST['score'] ?? "");    if ($name === "") {        $error = "姓名不能为空!";    } elseif (!is_numeric($score) || $score < 0 || $score > 100) {        $error = "分数必须是0~100之间的数字!";    } else {        $student_scores[$name] = (float)$score;        $_SESSION['student_scores'] = $student_scores;        header("Location: ".$_SERVER['PHP_SELF']);        exit;    }}

• trim() 清除输入首尾空格,?? "" 防止未传参时报错

• 三层校验:姓名非空、分数为数字、分数区间 0-100

• 同名覆盖实现修改分数功能,新名字实现新增学生

• header() 自刷新页面,避免用户重复提交表单

等级判定与平均分函数

function getGrade(float $score): string {    if ($score >= 90) return "A";    elseif ($score >= 80) return "B";    elseif ($score >= 70) return "C";    elseif ($score >= 60) return "D";    else return "F";}function average(array $scores): float {    $total = 0; $count = 0;    foreach ($scores as $score) {        $total += $score; $count++;    }    return $count > 0 ? $total / $count : 0.0;}

• 两个函数都用了类型声明:参数类型和返回值类型都明确指定

• average 里的三元判断防止数组为空时除以 0 报错

极值统计

$max_score = 0; $max_student = "";$min_score = 100; $min_student = "";foreach ($student_scores as $name => $score) {    if ($score > $max_score) { $max_score = $score; $max_student = $name; }    if ($score < $min_score) { $min_score = $score; $min_student = $name; }}

• 预设最大值初始为 0、最小值初始为 100,foreach 遍历时实时更新

删除逻辑

if (isset($_GET['delname'])) {    $delName = $_GET['delname'];    if (isset($student_scores[$delName])) {        unset($student_scores[$delName]);        $_SESSION['student_scores'] = $student_scores;        $msg = "已删除学生:{$delName}";    }    header("Location: ".$_SERVER['PHP_SELF']);    exit;}

• GET 参数接收删除指令,unset() 删除数组指定键

• 前端删除按钮用 urlencode() 防中文乱码,onclick confirm() 二次确认防误删

十、运行测试

把代码保存为 grade.php,放到 xampp/htdocs 目录,浏览器访问 http://localhost/grade.php,页面会加载 5 条初始学生数据。

功能验证清单:

• 新增学生:输入全新姓名 + 分数,提交后表格多一行,总人数 +1

• 修改分数:输入已有姓名 + 新分数,提交后对应行分数更新

• 姓名为空:红色提示"姓名不能为空!"

• 分数越界:输入 105 或 -5,提示"分数必须是0~100之间的数字!"

• 数据持久化:刷新页面,数据不丢失;关闭浏览器重开,数据清空

• 自动评级:90+ 为 A,80-89 为 B,70-79 为 C,60-69 为 D,60 以下为 F

• 极值统计:多组数据下,自动展示当前最高分和最低分学生

• 删除功能:点删除按钮弹窗确认,确认后该行消失,统计自动重算

十一、小结

• 条件判断:if/else/elseif 处理分支逻辑,switch 适合多值匹配,注意 break 不能漏

• 循环:while 先判断后执行,do...while 至少执行一次,for 适合计数循环,foreach 专门遍历数组

• 循环控制:break 跳出整个循环,continue 跳过本次

• 函数:function 定义,参数传入、return 返回。支持默认值、可变参数、类型声明

• 作用域:局部和全局隔离,优先用参数传值,少用 global;static 变量跨调用保留

• 匿名函数与箭头函数:现代 PHP 的简洁写法,常用于回调和临时逻辑

本文基于作者实际学习与项目经验整理,代码示例均已在本地环境测试通过。文字整理过程中借助了 AI 工具辅助排版。

本文配套资料包

完整代码文件
速查手册
实战练习题
面试考点卡
公众号回复php03获取

资料下载

-END-

最新文章

随机文章