← Назад к вопросам

Что такое итератор?

2.0 Middle🔥 171 комментариев
#PHP Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое итератор?

Итератор — это объектно-ориентированный паттерн проектирования, а также конкретная реализация в виде интерфейса в PHP, предоставляющая стандартный способ последовательного доступа к элементам коллекции (например, массива, списка, дерева или любого другого агрегированного объекта) без раскрытия его внутренней структуры. Итератор позволяет обходить элементы коллекции независимо от её конкретной реализации.

Ключевая идея и преимущества

Итератор решает несколько важных задач:

  • Инкапсуляция логики обхода: Алгоритм перемещения по коллекции скрыт внутри итератора, а не размазан по клиентскому коду.
  • Единообразный доступ: Разные коллекции (массив, результат запроса к БД, дерево) могут обходиться с помощью одного и того же интерфейса.
  • Позволяет иметь несколько одновременных обходов: Для одной коллекции можно создать несколько независимых итераторов.
  • Ленивая загрузка (lazy loading): Элементы могут подгружаться по мере необходимости (например, при чтении больших результатов из базы данных), что экономит память.

Интерфейсы итераторов в PHP

PHP предоставляет встроенную иерархию интерфейсов для работы с итераторами, ядром которой является интерфейс \Iterator.

Базовый интерфейс \Iterator

Этот интерфейс требует реализации пяти ключевых методов:

interface Iterator extends Traversable {
    // Возвращает текущий элемент
    public function current(): mixed;

    // Переходит к следующему элементу
    public function next(): void;

    // Возвращает ключ текущего элемента
    public function key(): mixed;

    // Проверяет, корректна ли текущая позиция
    public function valid(): bool;

    // Возвращает итератор к первому элементу
    public function rewind(): void;
}

Расширенные интерфейсы

  • \IteratorAggregate — более простой интерфейс для объектов, которые могут предоставить внешний итератор. Требует реализации лишь одного метода getIterator().
  • \SeekableIterator — добавляет возможность перехода к произвольной позиции с помощью метода seek().
  • \Countable — часто используется вместе с итераторами для получения количества элементов.

Практический пример реализации итератора

Представим, что нам нужно итерироваться по коллекции пользователей, загружая их данные "лениво".

class UserCollectionIterator implements \Iterator {
    private array $userIds;
    private int $position = 0;
    private ?User $currentUser = null;

    public function __construct(array $userIds) {
        $this->userIds = $userIds;
    }

    public function current(): ?User {
        if ($this->currentUser === null) {
            $this->currentUser = UserRepository::find($this->userIds[$this->position]);
        }
        return $this->currentUser;
    }

    public function next(): void {
        $this->position++;
        $this->currentUser = null; // Сбрасываем кэш при переходе
    }

    public function key(): int {
        return $this->position;
    }

    public function valid(): bool {
        return isset($this->userIds[$this->position]);
    }

    public function rewind(): void {
        $this->position = 0;
        $this->currentUser = null;
    }
}

// Использование
$userIds = [1, 3, 7, 15];
$iterator = new UserCollectionIterator($userIds);

foreach ($iterator as $user) {
    echo $user->getName() . "\n";
}

Итераторы в современном PHP (Generators)

Начиная с PHP 5.5 появилась более простая альтернатива — генераторы. Они позволяют создавать итераторы без явной реализации интерфейса, используя ключевое слово yield.

function getUserGenerator(array $userIds): \Generator {
    foreach ($userIds as $id) {
        // Данные загружаются только при очередной итерации
        yield UserRepository::find($id);
    }
}

foreach (getUserGenerator([1, 3, 7, 15]) as $user) {
    echo $user->getName() . "\n";
}

Генераторы существенно упрощают код, особенно когда требуется ленивая загрузка данных или работа с большими наборами данных, которые нецелесообразно загружать в память целиком.

Преимущества использования итераторов в Backend-разработке

  1. Работа с большими данными: Итераторы и генераторы позволяют обрабатывать огромные наборы данных (например, результаты SQL-запросов) без перегрузки памяти.
  2. Унификация API: Вы можете создавать сервисы, которые работают с любыми коллекциями через единый интерфейс.
  3. Тестируемость: Итераторы легко тестировать и мокировать благодаря чёткому контракту интерфейсов.
  4. Интеграция со SPL: Множество встроенных классов PHP (например, ArrayIterator, FilesystemIterator) реализуют эти интерфейсы, обеспечивая согласованность.
  5. Поддержка foreach: Любой объект, реализующий \Traversable (родительский интерфейс для \Iterator), может использоваться в конструкции foreach.

В современной PHP-разработке понимание итераторов критически важно для создания эффективных, масштабируемых и поддерживаемых приложений, особенно когда речь идет о обработке данных, работе с файлами или потоковой передаче контента.

Что такое итератор? | PrepBro