Precisa de conselhos de iterador para atravessar a tree

Oi, eu preciso de alguns conselhos de iterador.

Eu tenho um object de categoria que pode conter uma coleção de itens e também pode ter categorias de crianças.

Da doctrine ORM recebo uma coleção de objects de categoria. Agora eu quero atravessar esta coleção e aplainar a estrutura de tree da categoria. Portanto, as categorias de crianças estão no mesmo nível do pai. Eu também gostaria de filtrar as crianças.

Talvez alguém possa me apontar na direção certa, atualmente um pouco perdido na nuvem do Iterator.

parent; } public function setItems($items) { $this->items = $items; } public function getItems() { return $this->items; } //colelction of categories public function getChildren() { return $this->children; } } 

   

Você simplesmente precisa implementar a interface RecursiveIterator . Então, você pode iterar sobre ele usando o concreto RecursiveIteratorIterator .

Para ajudá-lo a entender …

Um RecursiveIterator não é muito, um, “recursivo” por si só. É apenas algo que oferece certos methods que podem ser usados ​​para obter as crianças (o subproblema em recursion pode ser pensado como “crianças”). Observe que RecursiveIterator.getChildren () deve retornar seus filhos na forma de outro RecursiveIterator .

Você poderia iterar manualmente um RecursiveIterator simples, mas seria muito doloroso acompanhar todos os getChildren sub retornados pelas chamadas recursivas para getChildren , e manter a profundidade adequada etc … é aí que RecursiveIteratorIterator entra …

Um RecursiveIteratorIterator é o que faz o trabalho real para atravessar sistematicamente a estrutura, imitando a recursion. Ele itera através de um RecursiveIterator como se fosse uma lista plana, mas em cada elemento da lista, ele testa o elemento atual para a presença de crianças. Se ele tiver hasChildren , ele chama getChildren e armazena a referência a este novo iterador infantil em uma pilha. Ele gerencia o Stack de uma forma que fornece o comportamento recursivo que você espera (da mesma forma que você transforma manualmente uma function recursiva em uma versão iterativa).

Para ser claro, você não codifica seu próprio RecursiveIteratorIterator , apenas instancia a implementação concreta do php. Esta class existe puramente para esconder as complicações e gerenciar todos os muitos objects RecursiveIterator que se instanciam no processo transversal de você e apresentando o resultado do percurso para você como o que parece ser uma lista plana. RecursiveIteratorIterator é uma class muito complicada internamente.

Quanto à filtragem –

Há algumas maneiras. Para facilitar o uso, recomendo usar CallbackFilterIterator se você tiver o php 5.4. Caso contrário, você deve estender FilterIterator .

No entanto, ambos filtram os elementos após a vista, a vista da estrutura recursiva foi achatada em uma lista como a estrutura. Portanto, seu filtro não pode, por exemplo, dizer “ignorar esta subtree inteira”, ele só pode dizer “ignorar este único elemento”. Se você precisa dizer “ignorar esta subtree inteira”, você precisa usar RecursiveCallbackFilterIterator ou estender RecursiveFilterIterator se você não possui php 5.4

você provavelmente quer começar com

 class RecursiveCategoryIterator implements RecursiveIterator {... 

E isso deve conter uma lista de objects de categoria.

Você deve começar no nó da raiz e percorrer recursivamente cada $this->getChildren() (dos nós e os subnodos (e seus subnodos (e seus subnodos (e seus subnós))) (recursion) até que seja null . Isso resultará em algo como isto:

 (Start) Root node -> 1st Child node --> Grandchild node -> 2nd Child node -> 3rd Child node -> 4th Child node --> Grandhild node (No more children so exit)