Привет, мне нужен совет итератора.
У меня есть объект Category, который может содержать набор элементов, а также может иметь дочерние категории.
Из доктрины ORM я получаю коллекцию объектов категории. Теперь я хочу пройти эту коллекцию и сгладить структуру древа категории. Таким образом, категории детей находятся на том же уровне, что и его родитель. Я также хотел бы отфильтровать детей.
Может быть, кто-то может указать мне в правильном направлении, в настоящее время немного потерянный в облаке Итератора.
<?php class Category { private $name; private $children; private $type; private $parent; private $items; //parent category public function getParent() { return $this->parent; } public function setItems($items) { $this->items = $items; } public function getItems() { return $this->items; } //colelction of categories public function getChildren() { return $this->children; } }
Вам просто нужно реализовать интерфейс RecursiveIterator . Затем вы можете перебирать его с помощью конкретного RecursiveIteratorIterator .
Чтобы помочь вам понять …
RecursiveIterator
не очень-то, «рекурсивный» сам по себе. Это просто то, что предлагает определенные методы, которые могут быть использованы для получения детей (подзадача в рекурсии можно рассматривать как «дети»). Обратите внимание, что RecursiveIterator.getChildren
() должен возвращать свои дочерние элементы в виде другого RecursiveIterator
элемента.
Вы можете вручную перебрать простой RecursiveIterator
элемент, но было бы очень сложно отслеживать все вспомогательные итераторы, возвращаемые рекурсивными вызовами getChildren
, и поддерживать правильную глубину и т. Д. … там, где входит RecursiveIteratorIterator
…
RecursiveIteratorIterator
– это то, что делает фактическую работу для систематического прохождения структуры, имитируя рекурсию. Он выполняет итерацию через RecursiveIterator
как если бы это был плоский список, но у каждого элемента в списке он проверяет текущий элемент на наличие дочерних элементов. Если он hasChildren
, он вызывает getChildren
и сохраняет ссылку на этот новый дочерний итератор в стеке. Он управляет Stack таким образом, который обеспечивает ожидаемое рекурсивное поведение (почти так же, как вы вручную преобразуете рекурсивную функцию в итеративную версию).
Чтобы быть ясным, вы не кодируете свой собственный RecursiveIteratorIterator
, просто создайте конкретную реализацию php. Этот класс существует только для того, чтобы скрыть сложности и управлять всеми многими объектами RecursiveIterator
которые получают экземпляр в процессе обхода от вас, и представляя результат обхода вам как то, что кажется плоским списком. RecursiveIteratorIterator
– очень сложный класс внутри.
Что касается фильтрации,
Есть несколько способов. Для удобства использования я рекомендую использовать CallbackFilterIterator, если у вас есть php 5.4. В противном случае вы должны расширить FilterIterator .
Тем не менее, оба из этих фильтров выделяют элементы после представления um, рекурсивной структуры, сглаживаются в структуру списка. Таким образом, ваш фильтр не может, например, сказать «пропустить все это поддерево», он может только сказать «пропустить этот единственный элемент». Если вам нужно сказать «пропустить все это поддерево», вам нужно использовать RecursiveCallbackFilterIterator или расширить RecursiveFilterIterator, если у вас нет php 5.4
вы, вероятно, хотите начать с
class RecursiveCategoryIterator implements RecursiveIterator {...
И это должно содержать список объектов категории.
Вам нужно начинать с корневого узла и рекурсивно пересекать каждый $this->getChildren()
(узлов и поднодов (и их подносы (и их подносы (и их подноды)))) (рекурсия), пока не станет null
. Это приведет к чему-то вроде этого:
(Start) Root node -> 1st Child node --> Grandchild node -> 2nd Child node -> 3rd Child node -> 4th Child node --> Grandhild node (No more children so exit)