while先判断后执行,do-while先执行后判断;后者在条件初始为假时仍执行一次循环体,易导致null访问错误,适用于必须至少尝试一次的场景。

while 和 do-while 的执行顺序差异直接决定空数据行为
关键区别不在语法多一个 do,而在「判断时机」:while 是先判后跑,do-while 是先跑再判。这意味着哪怕条件一开始就不成立,do-while 也会至少执行一次循环体。
常见错误现象:while ($row = mysqli_fetch_assoc($result)) { ... } 在查询无结果时完全不进循环,这是对的;但若误写成 do { ... } while ($row = mysqli_fetch_assoc($result));,就会因先执行导致 $row 为 null 后还试图访问字段,触发 Notice: Trying to access array offset on value of type null。
- 适用场景:
do-while适合「必须至少尝试一次」的逻辑,比如读取用户输入直到合法、重试网络请求、生成唯一 ID 等 - 性能上无差别,但语义更明确——用错会立刻暴露逻辑漏洞
- PHP 8.0+ 对
do-while的解析更严格,空循环体(do ; while(0);)需确保分号存在,否则报Parse error: syntax error, unexpected ';'
while 循环里忘记更新条件变量是高频死循环原因
不是 PHP 特有,但新手在处理数据库游标、文件读取或状态机时特别容易漏掉 $i++ 或 mysqli_fetch_* 这类推进动作。
典型错误代码:while ($i —— 输出无限个 0,因为 $i 始终没变。
- 检查点:循环体内是否至少有一处修改了
while括号里的任意变量 - 数据库场景中,别把
mysqli_fetch_assoc()放在循环外,否则永远读同一行 - 用
for替代简单计数型while更安全,因为初始化、条件、递增都在一行,视觉上不易遗漏
while 中使用赋值表达式当条件要小心真假值陷阱
像 while ($line = fgets($fp)) 看似简洁,但 fgets() 返回 false 表示 EOF,返回空字符串 "" 却是真实内容——而 "" 在布尔上下文中为 false,会导致提前退出。
同样问题出现在 mysqli_fetch_array():如果某字段值是 0、"0"、null 或空数组,整个表达式可能被误判为假。
- 正确写法应显式判断是否为
false:while (($line = fgets($fp)) !== false) - 数据库遍历时推荐用
while ($row = mysqli_fetch_assoc($result)),因为mysqli_fetch_assoc()只在无更多行为时返回null,且null === false不成立,所以能安全进入循环 - 避免在条件中混用
==,一律用===防止类型隐式转换干扰判断
do-while 用在函数末尾做「后置检查」比 while 更自然
当逻辑天然要求「做完再看要不要重来」,比如解析配置项、校验密码强度、生成随机字符串防冲突,do-while 的结构和人类思维一致,不用预先构造初始值。
示例:生成不含连续重复字符的 6 位随机码
do {
$code = substr(str_shuffle('ABCDEFGHJKLMNPQRSTUVWXYZ23456789'), 0, 6);
} while (preg_match('/(.)\1/', $code));
这里没法预知第一次生成是否合格,也不需要先定义 $code 初始值——而用 while 就得绕一圈:
$code = '';
while (preg_match('/(.)\1/', $code)) {
$code = substr(str_shuffle('...'), 0, 6);
}
这反而引入了未定义行为风险(第一次判断时 $code 是空字符串,但正则仍可运行,只是逻辑反直觉)。
- 注意:PHP 中
do-while的分号不能省,} while(...)后必须有;,否则 Parse error - 嵌套时缩进易混乱,建议只用于单层逻辑,复杂流程拆成函数更清晰
实际写的时候,最容易被忽略的是「空结果下 do-while 的第一次执行是否合理」——它不看你有没有数据,只看你写了没写。这个「强制执行一次」的特性,用对了是利器,用错了就是静默 bug。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











