应直接用 foreach 替代 each(),因其性能、可读性、安全性更优;自定义 myeach() 易出错且掩盖过时逻辑;改写时无需 reset(),嵌套结构需逐层 foreach 展开并校验数组类型。

直接替换为 foreach,别写自定义 myEach() —— 99% 的场景下它既不必要,还容易出错。
为什么不能简单用自定义函数模拟 each()
很多开发者看到旧代码里有 while (list($k, $v) = each($arr)),第一反应是“我写个 myEach() 补上就行”。但问题在于:
-
each()返回的是带数字索引(0、1)和字符串索引('key'、'value')的混合数组,手动构造极易漏掉某个键或顺序错位; - PHP 8.1 对数组内部指针操作更严格,
key()/current()/next()组合在某些边界情况(如空数组、引用传递后)行为不稳定; - 自定义函数无法复现
each()和list()在 PHP 7.x 中的隐式解构逻辑,尤其当数组含非标量键时容易触发Notice: Undefined offset; - 哪怕函数能跑通,也掩盖了真正的问题:这种遍历方式本身已过时,且
foreach在性能、可读性和安全性上全面胜出。
while (list($k, $v) = each($arr)) 怎么安全改写
这是最常见、也最容易误改的模式。原始写法依赖数组内部指针,而 foreach 是独立迭代器,无需重置、不干扰原数组状态。
正确改法就是直译语义:
// ❌ PHP 7.0 原写法
reset($arr);
while (list($k, $v) = each($arr)) {
echo "$k => $v\n";
}
// ✅ PHP 8.1 推荐写法
foreach ($arr as $k => $v) {
echo "$k => $v\n";
}
注意点:
- 不需要
reset()——foreach每次都从头开始; - 如果原逻辑中在循环内修改了
$arr(比如unset()或追加元素),需确认是否真需要边遍历边改;PHP 8.1 下这类操作更易触发未定义行为,建议先$keys = array_keys($arr)再遍历键名; - 若原代码依赖
each()返回false来判断结束,foreach本身无返回值,但循环自然终止即等效。
关联数组 + 多维结构下的特殊处理
有些老代码会嵌套使用 each(),例如解析配置数组或树形结构:
// ❌ 危险写法(PHP 8.1 报 Fatal error)
while (list($section, $items) = each($config)) {
while (list($key, $val) = each($items)) {
// ...
}
}
这类结构必须逐层展开,不能靠“指针继承”:
- 外层用
foreach ($config as $section => $items); - 内层用
foreach ($items as $key => $val); - 如果
$items可能为null或非数组,加is_array($items)判断,避免Invalid argument supplied for foreach(); - 不要试图用
&$items引用去“延续”指针状态——PHP 8.1 的foreach引用行为与 PHP 7.x 已不同,可能造成意外覆盖或空引用。
真正难处理的不是语法替换,而是那些把 each() 当作“唯一遍历手段”、混用指针控制和业务逻辑的代码。它们往往缺乏单元测试,改完后必须验证所有分支路径,尤其是空数组、单元素、键名含数字或特殊字符的情况。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











