Signature
array_shift(array &$array): mixedPurpose
array_shift() takes the first element off an array. It returns that element and changes the array you passed in, so the array becomes one item shorter. It is the natural tool when you treat an array as a queue: you add work at the end and take work from the front.
Signature
The & means the argument is passed by reference. The function modifies your original variable instead of working on a copy. Because of that, you must pass a variable, not a literal array or the result of another function call.
Parameters and defaults
$array: the input array. It has no default value and it is required.
There are no optional parameters. The function always removes exactly one element, the first one in the array's current order. "First" means first by position, not the lowest key.
Return value and failure cases
The return type is mixed, because the removed element can be any value. On success you get that value. If the array is empty, you get null.
This creates one ambiguity: an array whose first element really is null also returns null. If that matters, check whether the array is empty before you shift it.
The parameter is declared as array, so in PHP 8 you should always pass an array. Do not rely on any behavior for non-array values; validate your input before calling.
Two side effects to remember:
- Integer keys of the remaining elements are renumbered, starting from zero.
- String keys are left alone.
- The internal array pointer is reset after the call.
Example 1: taking from a queue
The returned value and the shortened array are both useful, so capture them together.
$queue = ["orange", "banana", "apple"];
$first = array_shift($queue);
echo json_encode(["first" => $first, "queue" => $queue], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"first":"orange","queue":["banana","apple"]}
The remaining list is ["banana", "apple"], and its keys are now 0 and 1. A common loop pattern is while ($queue !== []) { $item = array_shift($queue); ... }, which avoids confusion with a stored null value.
Example 2: mixed keys
The renumbering rule only touches integer keys. String keys stay where they are, and the order of the remaining items is preserved.
$data = [5 => "a", "x" => "b", 9 => "c"];
$removed = array_shift($data);
echo $removed, "\n";
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";a
{"x":"b","0":"c"}
The element at key 5 was first, so it is removed. The item that had key 9 now has key 0, while "x" keeps its name. If your integer keys carry meaning, such as IDs, array_shift() will destroy that meaning. Use string keys or a different structure in that case.
Example 3: empty arrays and null values
An empty array and an array that starts with null both give null back, but only one of them changes.
$empty = [];
$fromEmpty = array_shift($empty);
$withNull = [null, 1];
$fromNull = array_shift($withNull);
echo json_encode([
"fromEmpty" => $fromEmpty,
"emptyAfter" => $empty,
"fromNull" => $fromNull,
"restAfter" => $withNull,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"fromEmpty":null,"emptyAfter":[],"fromNull":null,"restAfter":[1]}
Both calls return null. The only way to tell them apart is to look at the array before shifting, for example with $array === [] or count($array).
Edge cases
- Single-element array: shifting leaves an empty array.
- Nested arrays: the removed element can itself be an array. It is returned unchanged.
- Pointer reset: if you were iterating manually with
next()orcurrent(), the pointer is reset after each shift. Do not mix manual pointer iteration with shifting. - Shifting inside
foreach: aforeachover the same variable works on its own copy of the array, so shifting inside the loop does not shorten the loop. Use awhileloop when you want to consume the array. - Cost: because remaining integer keys are renumbered, shifting from very large lists over and over can become slow. For heavy queue work, consider tracking an index or using a dedicated queue structure.
Common mistakes
- Expecting a new array back. The return value is the removed element, not the shortened array. Writing
$list = array_shift($list);replaces your array with a single item. - Passing a non-variable. Because of the reference parameter, put the array in a variable first.
- Relying on integer keys. After a shift, a key like
9becomes0. Never use the numeric keys as stable identifiers when you also shift. - Treating
nullas always meaning empty. Check for emptiness explicitly ifnullis a legal value in your data. - Using it to read without removing. If you only want to see the first value, use
reset()or read the key directly.array_shift()always mutates.
Related functions
array_unshift()adds one or more elements to the start of an array.array_push()adds elements to the end.array_pop()removes and returns the last element, without renumbering the other keys.array_slice()returns part of an array without modifying the original.reset()moves the pointer to the first element and returns its value without removing it.
Recap
array_shift() removes the first element of an array variable, returns it, renumbers integer keys from zero, keeps string keys, and resets the array pointer. It returns null for an empty array, which is also what you get when the first element itself is null. Capture the returned value, do not reassign the array to it, and check for emptiness first when null is meaningful.
Tested examples
$queue = ["orange", "banana", "apple"];
$first = array_shift($queue);
echo json_encode(["first" => $first, "queue" => $queue], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"first":"orange","queue":["banana","apple"]}
$data = [5 => "a", "x" => "b", 9 => "c"];
$removed = array_shift($data);
echo $removed, "\n";
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";a
{"x":"b","0":"c"}
$empty = [];
$fromEmpty = array_shift($empty);
$withNull = [null, 1];
$fromNull = array_shift($withNull);
echo json_encode([
"fromEmpty" => $fromEmpty,
"emptyAfter" => $empty,
"fromNull" => $fromNull,
"restAfter" => $withNull,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";{"fromEmpty":null,"emptyAfter":[],"fromNull":null,"restAfter":[1]}