I have to cache a tree structure and access it later on. Problem: I really can't figure out how to declare the data so that it fits to RecursiveIteratorIterator
etc. It's probably a very n00bish question, but I have tried lots of combinations and ran out of ideas :-(
Conceptually the data looks like this:
ROOT code : 1111, label : Universe
- code : 2000, label : Asia
- code : 3203, label : Hongkong
-code : 2081, label: Greater Area
-code : 2041, label: Downtown
- code : 4020, label : Shanghai
- code : 6201, label : Africa
- code : 321, label : North America
I want to access all direct childs to a given code, e.g. for Asia Hongkong and Shanghai.
RecursiveIteratorIterator
seems to make this easy.
// looking for Asia with code = 2000
$iterator = new RecursiveIteratorIterator(new Universe_Tree($tree));
foreach ($iterator as $key => $item) {
if ($item->code == 2000) {
var_dump($iterator->callGetChildren());
}
}
Class Universe_Tree does not do much yet:
class Universe_Tree extends ArrayIterator implements RecursiveIterator {
public function hasChildren() {
return (is_array($this->current()));
}
public function getChildren() {
return new self($this->current());
}
}
My best approach was to create objects of each node and store them in a nested array
$universe = new stdClass();
$universe ->code = 1111;
$universe ->label = "Universe";
$tree = array(
array($universe,
array(
$asia,
(array($shanghai,$hongkong)),
$europe
// and so on
)
);
Unfortunately $iterator->callGetChildren()
does not return the children, just the current element. Probably because the nodes are not nested together correctly. I also tried to nest arrays with a parentId but this lead to an error message from ArrayIterator
that this is not an array or object, though according to var_dump
it was an array. What else could I try?
This is a kind of answer. Actually I gave up and went to a solution based on SimpleXML. Really simple and very few code. Eventually somebody will come across this question and my "solution" might be a way for him, too. So I'll include it here:
// data represented as xml
$xmlstring = <<<XML
<orgtree>
<level number="1">
<unit label="Universe" code="1111">
<level number="2">
<unit label="Asia" code="2000"></unit>
<level number="3">
<unit label="Hongkong" code="3203"></unit>
<level number="4">
<unit label="Greater Area" code="2081"></unit>
<unit label="Downtown" code="2041"></unit>
</level>
</level>
</unit>
<unit label="Africa" code="6201"></unit>
<unit label="North America" code="321"></unit>
</level>
</unit>
</level>
</orgtree>
XML;
$xml = simplexml_load_string($xmlstring);
// use xpath to select part of xml
foreach ($xml->xpath('//unit[@code="2000"]') as $parentUnit)
{
$subtree = $parentUnit->level;
foreach ($subtree->unit as $unit) {
var_dump($unit["label"]);
}
}