🐘 IteratorAggregate: твои коллекции станут сильнее

Коллекции - это круто. Но давайте честно: массивы кажутся проще. Почему я всё равно выбираю коллекции?

Когда в метод приходит массив, ты не знаешь, что внутри. array - это всё что угодно. Может, там Article, может, User, а может, вообще строки или null. В метод, который принимает массив, всегда придётся добавлять проверку каждого элемента.

С коллекцией иначе. Увидел в сигнатуре ArticleCollection - и сразу ясно: тут только статьи. IDE подскажет, какие методы есть у объекта. И если попытаешься положить туда что-то другое, код просто не выполнится (вернее, PHP выбросит ошибку).

Но у коллекций по умолчанию есть один минус - их нельзя перебирать в цикле. А итерировать их очень хочется, ради этого их в основном и делают.


🎯 Как обычно решают проблему

Коллекцию снабжают методом getItems:

class ArticleCollection
{
    private array $items = [];

    public function add(Article $article): void
    {
        $this->items[] = $article;
    }

    public function getItems(): array
    {
        return $this->items;
    }
}

А потом в сервисе:

$articles = new ArticleCollection();
$articles->add($article1);
$articles->add($article2);

foreach ($articles->getItems() as $article) {
    echo $article->getTitle();
}

Да, это работает, но это не наш подход. Коллекция должна сама уметь отдавать свои элементы для перебора. Без лишних движений.


🔥 Теперь прокачаем ArticleCollection

Добавляем реализацию интерфейса:

class ArticleCollection implements IteratorAggregate
{
    private array $items = [];

    public function add(Article $article): void
    {
        $this->items[] = $article;
    }

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

И теперь можно писать так:

$articles = new ArticleCollection();
$articles->add($article1);
$articles->add($article2);

foreach ($articles as $article) {
    echo $article->getTitle();
}

Коллекция стала полноценной - её можно наполнять, передавать в аргументы и итерировать.


🎯 Итог

Коллекции - это удобно. Наша коллекция стала сильнее, а её использование в коде добавило стабильности всему сервису.

Если у вас в проекте есть классы-коллекции с методом getItems() - присмотритесь к ним. Возможно, они хотят стать итераторами :)


💬 Обсудить пост:

🔥 И не забудь подписаться :)