最安全的路径是直接用 foreach 替代 while + each;PHP 7.2 起 each() 触发 E_DEPRECATED,7.4 完全移除,其依赖数组指针的行为与 foreach 的独立迭代器语义不同,必须重构而非简单替换函数名。

直接用 foreach 替代 while + each 是最安全的路径
PHP 5.6 中常见的 while (list($key, $value) = each($arr)) 模式,在 PHP 7.2 起就报 E_DEPRECATED,到 PHP 7.4 已完全不可用。这不是语法错误,而是运行时警告 → 实际执行会跳过循环体,导致逻辑静默失效。必须改,且不能只改函数名。
- 原写法依赖数组内部指针,
each()每次调用后自动next();foreach是独立迭代器,不干扰原数组指针(也不需要) -
foreach ($arr as $key => $value)语义等价、性能更好、可读性更强,且兼容 PHP 5.6+ 所有版本 - 如果旧代码里混用了
reset()、current()、key()等指针操作,要一并清理——这些在foreach场景下纯属冗余
遇到 list() + each() 嵌套结构,别硬拆,重写逻辑
比如这种典型模式:while (list($k, $v) = each($data)) { if ($k === 'name') { ... } }。强行替换成 foreach 后再用 if 判断键名,看似可行,但容易漏掉原逻辑中隐含的“顺序敏感”或“中途 break”行为。
- 先确认是否真需要按插入顺序遍历:PHP 7.4 的关联数组默认保持插入顺序,
foreach也按此顺序,一般没问题 - 如果循环里有
break或continue,直接平移过去即可;但注意each()在break后指针停在哪,而foreach没有“暂停指针”的概念——它就是一次完整遍历 - 若原逻辑靠多次
each()调用实现“分段读取”,比如分页处理大数组,应改用array_slice()+foreach,或引入生成器(yield)流式处理
自定义 myEach() 不推荐,除非你控制全部调用点
网上流传的 myEach() 实现,多数返回结构错误:比如写成 [$key, $val, 'key', 'value' => $val],漏了 'key' => $key,导致 list($k, $v) = myEach($arr) 解构失败($k 变成字符串 'key' 而非实际键名)。
- 即使修复结构,
myEach()仍无法复现each()与reset()/current()的联动行为,尤其在嵌套循环或函数传参时极易出错 - PHP 7.4 已无
each(),但仍有key()、current()、next()等函数——它们没被废弃,只是不推荐用于遍历 - 真正需要手动控制指针的场景极少,常见于解析协议帧、状态机驱动数据流等底层操作;普通业务代码请坚定转向
foreach
升级时最容易忽略的坑:引用传递和副作用
旧代码中,each() 返回的是值拷贝,不影响原数组;但若你在 while 循环里对 $arr 做了修改(如 unset($arr[$key])),each() 的指针行为会变得不可预测。而 foreach 默认遍历的是数组快照,修改原数组不影响当前迭代。
立即学习“PHP免费学习笔记(深入)”;
- 如果循环中确实要动态增删元素,用
foreach ($arr as $key => &$value)显式加引用,再配合unset($arr[$key])—— 但 PHP 7.4 会触发“修改正在遍历的数组”警告,建议改用array_keys()先收集待删键,循环结束后统一unset() - 检查是否有函数通过
func_get_args()或反射捕获了each()返回值结构,这类元编程代码需同步重构 - CI/CD 流水线里跑的测试用例,可能还依赖
each()的返回格式断言,记得更新断言逻辑
each 的废弃不是孤立事件,它背后是 PHP 迭代模型的统一:数组、对象、Generator 都该用 foreach。硬扛兼容只会让问题滚雪球——越晚动,越难动。



















