Arr::isList
Reports whether an array's keys are sequential integers starting at zero with no gaps.
public static function isList($array)- Added in Laravel 8.x
Parameters
| Parameter | Type | Description |
|---|---|---|
$$array | array | The array to test. Must be an array; other types raise a TypeError. |
Return value
boolTrue when the keys are 0, 1, 2 … with no gaps and no string keys; false otherwise.
Errors
A TypeError is raised if the argument is not an array, because the check is delegated to PHP's array_is_list().
Arr::isList is a thin wrapper over PHP's array_is_list(). It is true when the keys are exactly 0, 1, 2, … in order with no gaps and no string keys. It is the property that decides whether json_encode emits a JSON array or a JSON object, which makes it the fastest way to explain a payload that suddenly changed shape.
When to reach for it
Reach for it before serialising something you filtered, and when a function must accept either one item or a list of them — testing for a list is a reliable way to branch. It is also worth an assertion in tests over any endpoint that must always return an array.
What trips people up
Almost every accidental non-list comes from a key-preserving operation: array_filter, unset, Arr::forget and array_diff all leave holes in the numbering, and the array then encodes as an object with numeric string keys. Two other details: an empty array is a list, and order counts — [1 => 'a', 0 => 'b'] has the right keys in the wrong order and is not a list. array_values() is the fix in every case.
Example
When to use it
- Checking that a filtered array will still encode as a JSON array and not an object.
- Branching between "a single item" and "a list of items" in a flexible API argument.
- Asserting in a test that an endpoint returns a JSON array.
Frequently asked questions
Is an empty array a list?
Yes, Arr::isList([]) returns true because there are no keys to violate the sequence.
Why is my array not a list after array_filter?
array_filter preserves the original keys, so removed elements leave gaps in the numbering. Wrap the result in array_values() to renumber it from zero.
How does Arr::isList relate to JSON encoding?
json_encode emits a JSON array only for a list and a JSON object otherwise, so this check tells you in advance which shape a payload will serialise to.
More examples
Why the JSON shape changed
Prints bool(false), then {"0":{"id":1},"2":{"id":3}}, then [{"id":1},{"id":3}]. Removing an element leaves keys 0 and 2, so the array is no longer a list and json_encode switches to an object. Clients that expected an array break on the second line and work again on the third.
<?php
use Illuminate\Support\Arr;
$rows = [['id' => 1], ['id' => 2], ['id' => 3]];
unset($rows[1]);
var_dump(Arr::isList($rows));
echo json_encode($rows), "\n";
echo json_encode(array_values($rows)), "\n";Accepting one item or many
Prints [{"id":1}] then [{"id":1},{"id":2}]. A single associative record is not a list, so it gets wrapped; an existing list is passed through untouched. This is how a helper can accept either shape without a separate flag argument.
<?php
use Illuminate\Support\Arr;
function normalise(array $input): array
{
return Arr::isList($input) ? $input : [$input];
}
echo json_encode(normalise(['id' => 1])), "\n";
echo json_encode(normalise([['id' => 1], ['id' => 2]])), "\n";After keyBy it is no longer a list
Prints bool(true), bool(false), then {"10":{"id":10,"name":"Desk"},"11":{"id":11,"name":"Chair"}}. Re-keying by a database id gives integer keys that do not start at zero, so the result is not a list and serialises as an object — usually the intent, but worth being deliberate about at an API boundary.
<?php
use Illuminate\Support\Arr;
$rows = [['id' => 10, 'name' => 'Desk'], ['id' => 11, 'name' => 'Chair']];
var_dump(Arr::isList($rows));
var_dump(Arr::isList(Arr::keyBy($rows, 'id')));
echo json_encode(Arr::keyBy($rows, 'id')), "\n";
Discussion