W3docs

is_iterable()

Функция is_iterable() в PHP 7.1+ проверяет, является ли переменная итерируемой — массивом или объектом с интерфейсом Traversable.

Введение

is_iterable() — встроенная функция PHP (доступна начиная с PHP 7.1), которая определяет, можно ли перебрать значение с помощью цикла foreach. Она возвращает true ровно для двух видов значений:

  • Массивы — любой массив является итерируемым.
  • Объекты, реализующие интерфейс Traversable — на практике это объекты, реализующие Iterator или IteratorAggregate, а также генераторы (функции, использующие yield).

Всё остальное — строки, целые числа, логические значения, null и обычные объекты (например, stdClass) — не является итерируемым, даже если интуитивно кажется «списком». На этой странице рассматриваются синтаксис, правила определения итерируемости, распространённые подводные камни и случаи, когда is_iterable() действительно полезна.

Синтаксис

is_iterable(mixed $value): bool

Функция принимает один аргумент, $value, и возвращает логическое значение:

АргументРезультат
Массивtrue
Объект Traversable (Iterator, IteratorAggregate, генератор)true
Всё остальное (строка, int, обычный объект, null, …)false

Начиная с PHP 8.0 существует соответствующий псевдотип iterable, который можно использовать в объявлениях типов — см. раздел Когда использовать ниже.

Базовый пример

php— editable, runs on the server

$var1 — массив, поэтому он итерируемый. $var2 — строка: хотя к символам строки можно обращаться по индексу, управлять ею через foreach нельзя, поэтому is_iterable() возвращает false.

Что считается итерируемым

Интересные случаи связаны с объектами. Объект является итерируемым только если он реализует Traversable (напрямую или через Iterator/IteratorAggregate), либо является генератором. Обычный объект итерируемым не является.

<?php
function genFn() {
    yield 1;
    yield 2;
}

class MyCollection implements IteratorAggregate {
    private array $items = [1, 2, 3];

    public function getIterator(): Iterator {
        return new ArrayIterator($this->items);
    }
}

var_dump(is_iterable([1, 2, 3]));      // bool(true)  array
var_dump(is_iterable(genFn()));        // bool(true)  generator
var_dump(is_iterable(new MyCollection())); // bool(true)  Traversable
var_dump(is_iterable("hello"));        // bool(false) string
var_dump(is_iterable(42));             // bool(false) int
var_dump(is_iterable(new stdClass())); // bool(false) plain object
var_dump(is_iterable(null));           // bool(false) null
?>

Главный вывод: stdClass (и любой объект без Traversable) возвращает false, даже несмотря на то что foreach может перебирать его публичные свойства. is_iterable() намеренно сообщает только о значениях, которые являются итерируемыми по контракту, а не случайно.

Распространённые подводные камни

  • Строки не являются итерируемыми. Строка — скалярное значение, а не коллекция, поэтому is_iterable("abc") возвращает false. Чтобы проверить строку, используйте is_string().
  • Обычные объекты не проходят проверку. is_iterable(new stdClass()) возвращает false. Если вам нужно лишь убедиться, что значение является каким-либо объектом, используйте is_object(); если же требуется именно перебираемый объект — вызывайте is_iterable().
  • Это не то же самое, что is_array(). is_array() возвращает true только для массивов и отклоняет генераторы и объекты Traversable. Используйте is_iterable(), когда нужно принимать и массивы, и объекты-итераторы.
  • null возвращает false. Передача неинициализированного или null-значения безопасна — функция просто вернёт false, не вызвав ошибки.

Когда использовать

Используйте is_iterable() как защитное условие перед foreach, чтобы функция могла принимать как массив, так и ленивый итератор, не аварийно завершаясь на некорректных входных данных:

<?php
function sumAll(mixed $data): int {
    if (!is_iterable($data)) {
        throw new InvalidArgumentException('Expected an iterable.');
    }

    $total = 0;
    foreach ($data as $value) {
        $total += $value;
    }
    return $total;
}

echo sumAll([1, 2, 3, 4]), "\n"; // 10

function counter() {
    yield 5;
    yield 10;
}
echo sumAll(counter()), "\n";     // 15
?>

Одна и та же функция работает и с обычным массивом, и с генератором, поскольку оба удовлетворяют условию is_iterable().

Нередко более чистым решением является объявление типа iterable (PHP 7.1+), которое позволяет PHP самостоятельно проверять ограничение и избавляет от ручной проверки:

<?php
function sumAll(iterable $data): int {
    $total = 0;
    foreach ($data as $value) {
        $total += $value;
    }
    return $total;
}
?>

Используйте функцию is_iterable(), когда значение имеет тип mixed и вы хотите ветвиться во время выполнения; используйте подсказку типа iterable, когда итерируемость является обязательным требованием к параметру.

Заключение

is_iterable() отвечает на один конкретный вопрос: можно ли перебрать это значение циклом foreach? Она возвращает true для массивов и объектов Traversable (включая генераторы) и false для всего остального. Используйте её как защитное условие для входных данных типа mixed, предпочитайте подсказку типа iterable, когда итерируемость обязательна, и помните, что функция строже, чем кажется — строки и обычные объекты не являются итерируемыми. Для связанных проверок смотрите is_array(), is_object() и gettype().

Практика

Практика
Какова функциональность функции 'is_iterable' в PHP?
Какова функциональность функции 'is_iterable' в PHP?
Was this page helpful?