Hi I need some iterator advice.
I have a Category object which can contain a collection of items and also can have children categories.
From doctrine ORM I do get a collection of category objects. Now I want to traverse this collection and flatten the category tree structure. So the children categories are at the same level as it’s parent. I would also like to filter the children.
Maybe somebody can point me in the right direction, currently a bit lost in the Iterator cloud.
<?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;
}
}
You simply need to implement the RecursiveIterator interface. Then, you can iterate over it using the concrete RecursiveIteratorIterator.
To help you understand…
A
RecursiveIteratorisn’t very, um, “recursive” by itself. It is just something that offers up certain methods that can be used to get the children(the subproblem in recursion can be thought of as “children”). Notice thatRecursiveIterator.getChildren() must return its children in the form of anotherRecursiveIterator.You could manually iterate a plain
RecursiveIterator, but, it would be pretty painful to keep track of all the sub iterators returned by the recursive calls togetChildren, and maintain the proper depth etc…thats whereRecursiveIteratorIteratorcomes in…A
RecursiveIteratorIteratoris the thing that does the actual work to systematically traverse the structure, mimicking recursion. It iterates through aRecursiveIteratoras if it were a flat list, but at each element in the list, it tests the current element for the presence of children. If ithasChildren, it callsgetChildrenand stores the reference to this new child iterator in a Stack. It manages the Stack in a fashion that provides the recursive behavior you expect(much the same way you manually transform a recursive function into an iterative version).To be clear, you don’t code your own
RecursiveIteratorIterator, just instantiate php’s concrete implementation. This class exists purely to hide the complications and manage all the manyRecursiveIteratorobjects that get instantiated in the traversal process from you, and presenting the result of the traversal to you as what seems like a flat list.RecursiveIteratorIteratoris a very complicated class internally.As for filtering-
There’s a few ways. For ease of use, I recommend to use CallbackFilterIterator if you have php 5.4. Otherwise, you must extend FilterIterator.
However, both of those filter the elements out after the, um, view of the recursive structure has been flattened into a list like structure. So, your filter cannot for example say “skip this entire subtree”, it can only say “skip this single element”. If you need to say “skip this entire subtree” you need to use RecursiveCallbackFilterIterator or extend RecursiveFilterIterator if you dont have php 5.4
you probably want to start with
And that should contains a list of Category objects.