Types7 min readExamples run on PHP 8.5.10

is_array()

Learn how PHP 8.4 is_array() tests for the array type, what it returns for objects, null and other values, and where it is easy to misuse.

Signature

is_array(mixed $value): bool

Purpose

is_array() answers one question: is the value you hold a PHP array right now? It is a type check, so it never converts anything and never looks inside the value. It is most useful at boundaries, where data arrives from somewhere you do not control: decoded JSON, function arguments declared as mixed, configuration trees or the results of other functions.

Signature

Parameters and defaults

$value is the only parameter. It is required and has no default. It accepts any type, which is the point of the function: you can pass a string, an integer, null, an object or an array without causing a type error.

Return value and failure cases

The function returns true when the value is an array and false for everything else. It does not throw exceptions for unexpected types, so there is no failure mode to catch. If you pass a variable that does not exist, PHP reports the undefined variable as usual and the function then sees null, so the result is false. Avoid relying on that. Initialise your variables, or use isset() or the null coalescing operator when a value may be missing.

Example 1: what counts as an array

Only real arrays return true, including empty ones. Objects, null, strings and numbers return false.

Example
<?php
$values = [[1, 2], 'text', 42, null, new stdClass(), []];
$results = [];
foreach ($values as $value) {
    $results[] = is_array($value);
}
echo json_encode($results);
Output
[true,false,false,false,false,true]

The first and last entries are arrays, so they give true. The other four give false.

Example 2: accepting several input shapes

A common use is a function that takes either a list or a single value and always returns an array. Check for an array first, then handle the scalar case.

Example
<?php
function normalizeTags(mixed $tags): array
{
    if (is_array($tags)) {
        return array_values($tags);
    }
    if (is_string($tags) && $tags !== '') {
        return [$tags];
    }
    return [];
}

echo json_encode([
    normalizeTags(['php', 'types']),
    normalizeTags('php'),
    normalizeTags(null),
    normalizeTags(['a' => 'x', 'b' => 'y']),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
[["php","types"],["php"],[],["x","y"]]

Note that array_values() drops the string keys of the last input, so the result is always a plain list.

Example 3: walking nested data and knowing the limits

When you process a tree of settings, is_array() separates branches from leaves. The same example shows two limits: an ArrayObject is an object, so it is not an array, and an array being an array says nothing about whether it is a list.

Example
<?php
$config = ['db' => ['host' => 'localhost'], 'debug' => false, 'paths' => ['a', 'b']];
$report = [];
foreach ($config as $key => $value) {
    $report[$key] = is_array($value) ? count($value) : 'scalar';
}
$report['arrayObject'] = is_array(new ArrayObject([1, 2]));
$report['list'] = is_array([3 => 'x']) && array_is_list([3 => 'x']);
echo json_encode($report, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"db":1,"debug":"scalar","paths":2,"arrayObject":false,"list":false}

The db branch has one entry and paths has two. debug is a leaf. The array [3 => 'x'] is an array but not a list, because its first key is not 0.

Edge cases

  • An empty array returns true. Use $value === [] or count() when you also need to know whether it has elements.
  • Objects that behave like arrays, such as ArrayObject or classes implementing ArrayAccess, return false.
  • A callable written as ['ClassName', 'method'] is an ordinary array, so is_array() returns true for it. Use is_callable() if you need to know whether it can be called.
  • Resources, closures, booleans, floats and strings all return false.
  • The function checks only the top level. A nested array does not change the answer for the outer one, and an array of strings is still just an array.

Common mistakes

  1. Treating a truthy value as an array. Code such as if ($data) is true for non-empty strings and objects too. Use is_array($data) when the type matters.
  2. Expecting is_array() to validate shape. It does not check keys, value types or list order. Combine it with array_is_list(), array_key_exists() or your own checks.
  3. Using it for anything you can loop over. Objects implementing Traversable work in foreach but fail is_array(). If you need to accept both, test for iterable in a type declaration or check is_iterable().
  4. Checking an array that came from json_decode() without the associative flag. By default JSON objects decode to stdClass, which is not an array. Pass true as the second argument if you want arrays.
  5. Calling it on a value that might not be defined. Prevent the warning by initialising the variable instead of relying on the null result.
  • array_is_list() checks whether an array has sequential keys starting at zero.
  • is_string(), is_int() and is_float() check other scalar types.
  • is_object() checks for objects, which is_array() never accepts.

Recap

is_array(mixed $value): bool returns true only for real PHP arrays, empty or not, and false for everything else, with no exceptions. It tests the type of the outer value only, so pair it with other checks when you also care about keys, contents or array-like objects.

Tested examples

Which values are arrays
<?php
$values = [[1, 2], 'text', 42, null, new stdClass(), []];
$results = [];
foreach ($values as $value) {
    $results[] = is_array($value);
}
echo json_encode($results);
Output
[true,false,false,false,false,true]
Normalizing input into a list
<?php
function normalizeTags(mixed $tags): array
{
    if (is_array($tags)) {
        return array_values($tags);
    }
    if (is_string($tags) && $tags !== '') {
        return [$tags];
    }
    return [];
}

echo json_encode([
    normalizeTags(['php', 'types']),
    normalizeTags('php'),
    normalizeTags(null),
    normalizeTags(['a' => 'x', 'b' => 'y']),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
[["php","types"],["php"],[],["x","y"]]
Nested data and the limits of is_array()
<?php
$config = ['db' => ['host' => 'localhost'], 'debug' => false, 'paths' => ['a', 'b']];
$report = [];
foreach ($config as $key => $value) {
    $report[$key] = is_array($value) ? count($value) : 'scalar';
}
$report['arrayObject'] = is_array(new ArrayObject([1, 2]));
$report['list'] = is_array([3 => 'x']) && array_is_list([3 => 'x']);
echo json_encode($report, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
Output
{"db":1,"debug":"scalar","paths":2,"arrayObject":false,"list":false}