array_shift 从数组开头移出并返回第一个元素,同时直接修改原数组、重排数字键;空数组返回 NULL,需用 === NULL 判断。

array_shift 会修改原数组,别指望它只读取
array_shift 的核心行为是「从数组开头移出并返回第一个元素」,同时**直接修改原数组**——这不是一个安全的取值函数,而是带副作用的变更操作。如果只是想看第一个元素,用 $arr[0] 或 reset($arr) 更合适;真要移除且需要那个值,才轮到 array_shift。
常见错误现象:
在 foreach 循环里反复调用 array_shift 想“逐个处理”,结果数组越变越短,循环提前结束或索引错乱。
- 它只作用于索引数组(含数字键),对关联数组也生效,但会重排所有数字键(比如
['a'=>1, 'b'=>2, 0=>3]移出后,剩下部分的数字键会被重新编号为0,1...) - 若数组为空,返回
NULL,不是空字符串或false,注意用=== NULL判断 - 性能上,它需要重建整个数组的键,对大数组(万级元素以上)明显比
unset($arr[key])+array_values()慢,但后者不保证“第一个”语义
和 array_unshift、array_pop、array_push 的行为对比要分清
这四个函数都直接改原数组,但方向不同:array_shift 和 array_unshift 操作数组开头(前者取,后者插);array_pop 和 array_push 操作结尾。容易混淆的是 array_shift 和 array_pop:它们都“移出并返回”,但一个在头一个在尾,对顺序敏感的场景(如队列 vs 栈)必须选对。
- 模拟队列(FIFO):用
array_push入队,array_shift出队 - 模拟栈(LIFO):用
array_push入栈,array_pop出栈 -
array_unshift插入到开头,会把原有所有键往后推,同样有重排开销,慎用于大数组
替代方案:不想改原数组时怎么安全取第一个元素
如果只是读取,array_shift 是杀鸡用牛刀。最轻量的是直接访问:$first = $arr[0] ?? null(PHP 7+ 空合并),或者用 reset($arr) 并配合 key($arr) / current($arr)。这些都不动原数组,也不重排键。
立即学习“PHP免费学习笔记(深入)”;
-
reset($arr)返回第一个元素值,同时将内部指针归位,适合配合each()或手动遍历 - 用
array_key_first($arr)(PHP 7.3+)能拿到第一个键名,再取值:$arr[array_key_first($arr)],对关联数组更准确 - 如果数组可能为空,所有直接下标访问都要加
??或isset()防 Notice
实际用例:处理待办任务队列时的典型写法
假设有个任务列表 $tasks = ['send_email', 'backup_db', 'clear_cache'],每次执行一个并移除:
$task = array_shift($tasks);
if ($task !== NULL) {
do_task($task);
}
// $tasks 现在是 ['backup_db', 'clear_cache']
这里的关键点是:必须检查 !== NULL,因为任务名可能是 '0' 或 false 字符串,用 if ($task) 会误判。另外,别在 while (!empty($tasks)) 里反复 array_shift 还同时用 count($tasks) 做条件——empty() 内部已足够,且更安全。
复杂点在于,一旦你开始混合使用 array_shift 和其他键操作(比如 unset 某个中间键),数组结构会变得难以预测;这种场景更适合用 SplQueue 或自己封装一个真正支持高效首尾操作的结构。



















