← PHP natsort()自然排序函数详解:让code2.php排在code12.php前面 PHP array_pad()函数详解:按长度补位数组的用法 →

PHP next()函数:数组内部指针前移的正确用法

著
原创 2026-10-08 PHP 已有人查阅

一、next()到底动了什么

PHP每个数组内部都维护着一个指针,指向“当前元素”。这个指针不是给人看的,是给一批内部函数用的,比如current()、next()、prev()、reset()、end()、key()。

next()做的事情就一句话:把指针往后挪一格,然后返回挪过去之后那个元素的值。

$company = array("java", "T", "point", "coding", "every language");
echo next($company);

输出是T。

这里有个细节值得注意:数组刚创建时,内部指针默认停在第一个元素java上。next()先把指针从java移到T,再返回T的值。它不是返回“当前元素的下一个”,而是“移动后指针所在的那个”。

函数原型:

mixed next(array &$array);

参数是引用传递,必须传变量。返回值类型是mixed——有下一个元素就返回它的值,没有就返回false。

二、返回false这件事,比想象中麻烦

如果数组里有个元素的值本身就是false、0、""或null,next()返回的时候你分不清是“到头了”还是“值就是false”。

$data = array("code1", false, "code3");
echo next($data); // false
echo next($data); // code3

第一次next()返回false,但指针其实正常移到了第二个元素,只是那个元素的值是false。你要判断是否真的走到末尾,不能只看返回值,得配合key()或current()。

我早期写过一个遍历逻辑,用while(($val=next($arr))!==false)来判断结束,结果数组里一旦有falsy值就提前跳出。后来改成用key()判断:

while (key($arr) !== null) {
    $val = current($arr);
    // 处理
    next($arr);
}

key()在指针越界后返回null,这个判断比!==false靠谱得多。

三、和current()、prev()配合看指针行为

单独看next()容易糊涂,把几个函数放一起就清楚了。

$subject = array("java", "c", "os", "compiler", "dbms");

echo current($subject), "\n"; // java
echo next($subject), "\n";    // c
echo next($subject), "\n";    // os

current()读的是指针当前所在的值,不移动指针。next()读的是移动之后的值。两者搭配就是“读一次、走一步”的节奏。

再看prev()加入后的情况:

$social = array("", "fb", "quora", "telegram", "whatsapp");

echo current($social), "\n"; // 
echo next($social), "\n";    // fb
echo prev($social), "\n";    // 
echo next($social), "\n";    // fb

prev()把指针往回挪一格并返回那个值。所以next再prev就回到了原位,再next又前进一格。

这里有个边界:如果指针已经在第一个元素,prev()会返回false,但指针不会跑到数组外面去,它还是停在第一个元素。同理,指针在之后一个元素时调next(),返回false,指针停在之后一个元素,不会越界。这个设计让指针在两端是“卡住”的,不会因为多调几次就跑飞。

四、next()和foreach的关系

很多人以为foreach也用内部指针,其实不是。foreach在PHP7之后操作的是数组的一个副本(写时复制机制),它有自己的遍历逻辑,不碰内部指针。

$arr = array("code1", "code2", "code3");
foreach ($arr as $v) {
    echo next($arr), "\n";
}

这段代码里next()操作的是原数组的指针,foreach走的是另一套。两者互不干扰,输出可能会让你意外。别在foreach里混用next(),逻辑会变得很难读。

那什么时候用next()?我的经验是:需要手动、有条件地逐步遍历数组时用它。比如解析一个扁平的token列表,遇到某个标记就跳过下一条,或者要回退一步重新读。这种“带状态的顺序访问”用next()和prev()比foreach灵活。普通遍历还是foreach更清楚。

五、一组完整的指针函数

和next()一起用的还有几个,放在一起记:

函数 作用 指针是否移动
current() 返回当前元素值 否
key() 返回当前元素键 否
next() 指针前移一位,返回新位置的值 是
prev() 指针后移一位,返回新位置的值 是
reset() 指针回到第一个元素,返回第一个元素值 是
end() 指针移到之后一个元素,返回之后一个元素值 是
each() 返回当前键值对并前移指针 是(PHP7.2起废弃,8.0移除)

each()已经不能用了,老代码里看到要换掉。替代方式就是current()+key()+next()三件套。

reset()在遍历开始前很有用。如果数组之前被next()动过,指针停在中间,直接遍历会从中间开始。加一句reset($arr)回到开头。

六、本节课程知识要点

  1. next()的作用是前移内部指针并返回新位置的值,不是返回“当前元素的下一个值”。

  2. 返回值是mixed,没有更多元素时返回false,但元素值本身可能是false,判断结束要用key()配合。

  3. 参数是引用传递,只能传变量。

  4. 指针到两端会卡住,不会越界,多次调用next()或prev()不会出错。

  5. foreach不使用内部指针,不要和next()混用。

  6. each()已在PHP8.0移除,老代码里的each()要替换成current()/key()/next()组合。

  7. reset()是遍历前的保险动作,确保指针从第一个元素开始。

七、几个实际项目里的用法和坑

解析配置行。我做过一个读取自定义配置格式的小工具,每行是一个指令,有的指令带参数占下一行。这时候用next()读下一行很自然:

$lines = file("config.txt", FILE_IGNORE_NEW_LINES);
reset($lines);
while (($line = current($lines)) !== false) {
    if (strpos($line, "include") === 0) {
        $nextLine = next($lines); // 读参数行
    }
    next($lines);
}

这里要小心:current($lines)!==false在行内容为空字符串时也会跳出,因为""!==false其实成立……等等,空字符串不等于false,这个判断是安全的。但如果某行内容恰好是"0","0"!==false也成立。真正危险的是用!=而不是!==。用严格不等于,可以避开大部分falsy值问题。

不要依赖next()做分页。有人把结果集当数组,用next()逐条取,取到false就认为结束。数据里只要有falsy值就出错。分页还是用索引或专门的游标变量,别把内部指针当业务状态用。

调试时注意指针位置。在函数里对传入的数组调了next(),如果参数是引用传递,调用方的数组指针也会被改。函数内部改指针这种事不容易被发现,排查起来很费时间。要么在函数开头reset(),要么避免在函数里操作传入数组的内部指针。

个人建议:日常遍历用foreach,需要回退或有条件跳步时再用next()/prev()。把内部指针当成一种“低级工具”,用的时候心里清楚它在哪,别让它隐式地影响别处的代码。

next()本身不复杂,复杂的是它牵扯的“数组内部指针”这个隐式状态。用对了,它能在顺序访问的场景里提供灵活控制;用错了,falsy值和跨函数指针污染会带来很难查的bug。记住三点:判断结束用key(),遍历前reset(),别和foreach混着用。

← PHP natsort()自然排序函数详解:让code2.php排在code12.php前面 PHP array_pad()函数详解:按长度补位数组的用法 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号