导读:本期聚焦于张立峰创作的《PHP 8.1 中替代已废弃 each() 函数的正确方法是什么?》,敬请观看详情。each() 函数早在 PHP 7.2 就被标记为废弃,到 PHP 8.0 彻底移除,不少升级到 PHP 8.1 的项目因此报错。这个函数原本的作用是返回数组当前键值对并将指针前移,如今完全可以由 foreach 循环配合 key 和 value 语法来替代。本文详细讲解 each() 的历史行为、迁移到 foreach 的具体写法、如何模拟 each() 的指针语义,以及 list() 与 foreach 组合、array_walk、生成器等多种替代方案的适用场景与性能差异,帮助你平滑完成旧代码改造。

从 PHP 7.2 开始,each() 函数就被标记为废弃,PHP 8.0 正式将它从语言中移除。如果你的项目升级到 PHP 8.1 后突然报出 Call to undefined function each() 的致命错误,说明代码里还残留着这种老式写法。本文将带你彻底理解 each() 的原始行为,并给出多种符合现代 PHP 风格的替代方案。

PHP 8.1 中替代已废弃 each() 函数的正确方法是什么?

先弄清楚 each() 原来到底做了什么

在旧版本 PHP 中,each() 接收一个数组,返回当前内部指针指向的键值对,然后把指针向前移动一位。返回值是一个包含四个元素的数组:键名出现在下标 0 和 key 两个位置,值出现在下标 1 和 value 两个位置。当指针越过数组末尾时,each() 返回 false。

正因为这种“取一次走一步”的特性,老代码里常见两种用法:一种是与 list() 配合在 while 循环里逐行解析数据;另一种是配合 reset() 手动控制遍历进度。看一段典型的旧代码:

<?php
$user = ['name' => 'Tom', 'age' => 28, 'city' => 'Beijing'];

// 旧式写法:PHP 8.1 中会直接报错
reset($user);
while (list($key, $value) = each($user)) {
    echo $key . ' => ' . $value . PHP_EOL;
}
?>

这段代码的问题不仅在于函数被移除,更在于它依赖数组的内部指针,而 foreach 从 PHP 7 开始已经不再操作内部指针(它会先保存再还原指针状态),所以直接替换时要注意语义差异。

首选方案:用 foreach 完整替代

绝大多数场景下,foreach 都是最佳替代品。它语法简洁、不依赖内部指针、性能也更好。上面的旧代码可以直接改写成:

<?php
$user = ['name' => 'Tom', 'age' => 28, 'city' => 'Beijing'];

foreach ($user as $key => $value) {
    echo $key . ' => ' . $value . PHP_EOL;
}
?>

foreach 有几个额外优势值得注意。第一,它不会修改数组的内部指针,遍历结束后原数组的指针状态保持不变,这在函数间传递数组时更安全。第二,PHP 7 之后 foreach 对数组的遍历做了引擎级优化,基于内部哈希表直接迭代,比 while 配合函数调用的方式快得多。第三,如果遍历的是大数组且不需要修改原数据,可以用引用遍历避免数组拷贝:

<?php
// 引用遍历,避免大数组复制开销
foreach ($user as &$value) {
    $value = strtoupper($value);
}
unset($value); // 遍历后务必释放引用,避免后续误修改

// 遍历完成后重置指针(如果其他代码依赖指针位置)
reset($user);
?>

需要特别提醒的是引用遍历后一定要 unset() 引用变量,否则后续同名变量赋值会意外修改数组最后一个元素,这是实际项目中最常见的坑之一。

必须保留指针语义时怎么办

有些遗留代码确实依赖 each() 的“取一个、停一步”特性,比如在多次调用之间分批消费数组。这种情况下,可以用 key()current()next() 三个函数组合模拟:

<?php
// 自定义函数模拟 each() 的行为
function myEach(array &$arr): ?array
{
    $key = key($arr);
    if ($key === null) {
        return null; // 指针已越过末尾
    }
    $result = [1 => current($arr), 'value' => current($arr),
               0 => $key, 'key' => $key];
    next($arr);
    return $result;
}

// 使用示例
reset($user);
while (($item = myEach($user)) !== null) {
    echo $item['key'] . ' => ' . $item['value'] . PHP_EOL;
}
?>

返回 null 而不是 false 是有意为之,因为 PHP 8.1 中数组元素本身不可能为 null 之外的歧义值,这样判断更严格。如果你的旧代码中数组值可能是 false,用 null 作为结束标记还能避免旧 each() 返回 false 时产生的逻辑混淆。

另一种更现代的思路是用生成器改造。把遍历逻辑封装成 Generator 函数,代码既保留惰性求值的特性,又完全不依赖指针:

<?php
function lazyEach(array $arr): Generator
{
    foreach ($arr as $key => $value) {
        yield [$key, $value];
    }
}

foreach (lazyEach($user) as [$key, $value]) {
    echo $key . ' => ' . $value . PHP_EOL;
}
?>

其他替代方案与选型建议

除了 foreach,PHP 还提供了几个针对性工具。array_walk() 适合对每个元素执行回调处理,不需要返回新数组时比较方便:array_walk($user, function ($value, $key) { echo "$key => $value\n"; });array_map()array_filter() 则适合转换和过滤,它们都是声明式写法,比命令式循环更直观。

选型时可以参考这样的原则:只是简单遍历就用 foreach;需要变换数据用 array_map;需要边遍历边根据条件筛选用 array_filter;需要逐条处理且有副作用时用 array_walk;跨函数分批消费数据时用生成器。至于模拟 each() 的自定义函数,只建议作为迁移过渡方案,长期保留会让代码显得过时。

最后建议在升级 PHP 8.1 之前,先用静态分析工具扫描整个项目中对 each()、create_function()、get_magic_quotes_gpc() 等已移除函数的调用,提前列出改造清单。改造 each() 时顺手把 while 加 list 的写法统一替换为 foreach,代码可读性和维护性都会明显提升,这也符合现代 PHP 的编码规范趋势。

PHP each函数foreach遍历数组遍历修改时间:2026-09-06 22:10:39

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260906/51828.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。