主题
循环
循环用来把同一段逻辑执行多次:数数、累加、按条件反复尝试。PHP 最基础的三种是 while、do...while、for。保存为 loop.php 后执行 php loop.php:
php
<?php
$i = 1;
while ($i <= 3) {
echo $i, "\n";
$i++;
}输出:
1
2
3while
while 先判断条件,为真才进入循环体;进一次、改一次用来判断的变量,条件变假就停:
php
<?php
$count = 3;
while ($count > 0) {
echo "还剩 {$count} 次\n";
$count--;
}
echo "结束\n";结构可以记成:
while (条件) {
// 要重复的语句
// 通常要在这里修改条件里用到的变量
}条件一开始就是假,循环体一次都不会执行:
php
<?php
$n = 0;
while ($n > 0) {
echo "不会出现\n";
}
echo "直接到这里\n";忘记在循环里更新变量,条件永远为真,就会死循环。终端里可按 Ctrl + C 中断:
php
<?php
$i = 1;
while ($i <= 3) {
echo $i, "\n";
// 漏了 $i++,会一直打印 1
}条件的真假规则和 条件语句 相同。用 $i <= 3 这种明确比较,不要依赖 while ($i) 那种隐式真假($i 为 0 时会停,阅读成本高)。
do...while
do...while 至少执行一次,然后再判断要不要继续:
php
<?php
$i = 1;
do {
echo $i, "\n";
$i++;
} while ($i <= 3);注意:while 后面有分号 ;,这是这句语句的结束,不是写漏了。
条件一开始为假时,对比最明显:
php
<?php
$n = 0;
do {
echo "至少一次,n = {$n}\n";
} while ($n > 0);
while ($n > 0) {
echo "while 不会进来\n";
}适合「先做,再看还要不要再来一遍」:读一次用户输入、先执行一次查询、至少打印一行提示等。能用 while 表达清楚时,不必特意换成 do...while。
for
次数明确、有计数器时,用 for 更紧凑。三个表达式写在同一对括号里:
php
<?php
for ($i = 1; $i <= 3; $i++) {
echo $i, "\n";
}三个部分:
| 位置 | 作用 | 上例 |
|---|---|---|
| 第一个 | 开始前执行一次,通常初始化计数器 | $i = 1 |
| 第二个 | 每次进入循环体之前判断,为假则结束 | $i <= 3 |
| 第三个 | 每次循环体结束之后执行,通常更新计数器 | $i++ |
和下面的 while 等价:
php
<?php
$i = 1;
while ($i <= 3) {
echo $i, "\n";
$i++;
}从大数往回数、隔步前进都可以:
php
<?php
for ($i = 5; $i >= 1; $i--) {
echo $i, "\n";
}
for ($i = 0; $i <= 10; $i += 2) {
echo $i, " "; // 0 2 4 6 8 10
}
echo "\n";三个部分都可以留空,但留空后很容易写成死循环,初学不要省略:
php
<?php
$i = 1;
for (; $i <= 3; ) {
echo $i, "\n";
$i++;
}for (;;) 条件永远为真,必须在循环体内 break 才能停,可读性差,正式代码用明确条件。
循环变量 $i、$j 只在计数时使用。PHP 没有块级作用域,for 里定义的 $i 在循环结束后仍然存在:
php
<?php
for ($i = 1; $i <= 3; $i++) {
// ...
}
echo $i, "\n"; // 4,最后一次 $i++ 之后条件失败才退出不要在循环外依赖这个值,需要总数请另用变量保存。
break 与 continue
两种循环里都可以用:
break:立刻离开当前循环continue:跳过本轮剩下的语句,进入下一轮(for仍会执行第三个表达式)
php
<?php
for ($i = 1; $i <= 10; $i++) {
if ($i === 3) {
continue; // 不打印 3
}
if ($i === 8) {
break; // 到 8 就整段结束,8 和后面都不打印
}
echo $i, "\n";
}输出:1 2 4 5 6 7。
嵌套循环时,break / continue 默认只作用于最内层。可以写 break 2 跳出两层,但层数一多就难读,更稳妥的是把内层抽成函数后 return。
switch 里的 break 只结束 switch,不会结束外层循环。循环套 switch 时若要同时离开循环,用 break 2,或先设标志变量。
嵌套循环
循环里再写循环,常用来处理「行 × 列」:
php
<?php
for ($row = 1; $row <= 3; $row++) {
for ($col = 1; $col <= 3; $col++) {
echo "({$row},{$col}) ";
}
echo "\n";
}内层循环每轮都会把内层计数器走完。注意内外层用不同变量($row / $col),不要共用一个 $i。
冒号语法
和 HTML 混写时可用 while: / endwhile;、for: / endfor;:
php
<?php $i = 1; ?>
<ul>
<?php while ($i <= 3): ?>
<li>第 <?= $i ?> 项</li>
<?php $i++; ?>
<?php endwhile; ?>
</ul>do...while 没有对应的冒号写法。纯 PHP 脚本用花括号即可。
该用哪一种
| 场景 | 选用 |
|---|---|
| 条件为真就重复,次数不预先知道 | while |
| 至少执行一次,再决定要不要继续 | do...while |
| 有明确起点、终点、步长(数 1 到 n) | for |
| 遍历数组、列表 | foreach(见下) |
三种都能互相改写。选最能表达「为什么停」的那种:数次数用 for,等某个状态变化用 while。
foreach(先认识)
PHP 里遍历数组几乎总是用 foreach,比自己维护下标更不容易出错。数组还没系统讲之前,先看一眼:
php
<?php
$langs = ["PHP", "HTML", "SQL"];
foreach ($langs as $lang) {
echo $lang, "\n";
}
foreach ($langs as $index => $lang) {
echo "{$index}: {$lang}\n";
}需要下标运算、隔几个取一个时,仍可用 for 配合 count()。日常「把每个元素处理一遍」优先 foreach。创建、增删、嵌套和常用函数见 数组。
书写建议
- 循环里必须能让条件变成假,否则就是死循环
- 计数用整数、用
===/<=写清边界,注意是$i < n还是$i <= n for的三个表达式各司其职:初始化、条件、更新,不要把更新藏到循环体角落又写进第三个表达式- 循环体只做本轮的事,累计值放在循环外的变量里
- 层数超过两层就考虑拆函数;
break 2能用,但不是第一选择
练习
- 用
while输出 1 到 10;再用for写一遍,确认结果一致。 - 用
for计算 1 到 100 的和,echo结果(应为5050)。 - 用
do...while演示「$n = 0时仍会执行一次」,并对照同条件的while。 - 用
for输出 1 到 20 中的偶数;用continue跳过奇数。