Представьте, что у вас есть дерево, представляющее семейство, которое вы хотите сохранить в таблицах, но сохранить уровни вложенности. Я хотел бы получить данные поста ниже в структуре ниже.
Я полагаю, что RecursiveIterator мог бы быть способом сделать это, но я не уверен, как бы я это сделал. У меня есть код, который работает в большинстве случаев, но он стал уродливым, раздутым. Я могу опубликовать это, если хотите.
stdClass Object
(
[name] => Smith
[type] => Family
[children] => Array(
[1] => stdClass Object
(
[name] => Michael
[type] => Uncle
[children] => Array(
[0] => stdClass Object
(
[name] => Jared
[type] => cousin
)
)
)
[2] => stdClass Object
(
[name] => Jeff
[type] => Dad
[children] => Array(
[0] => stdClass Object
(
[name] => Jonas
[type] => self
)
[1] => stdClass Object
(
[name] => Leah
[type] => sister
[children] => Array(
[0] => stdClass Object
(
[name] => Jacob
[type] => nephew
)
)
)
)
)
)
)
Записи на постоянство должны выглядеть так:
Array
(
stdClass Object ( [name] => Smith [type] => Family [subgroup] => 0 [parent_subgroup] => )
stdClass Object ( [name] => Michael [type] => Uncle [subgroup] => 1 [parent_subgroup] => 0 )
stdClass Object ( [name] => Jared [type] => Cousin [subgroup] => 2 [parent_subgroup] => 1 )
stdClass Object ( [name] => Jeff [type] => Dad [subgroup] => 1 [parent_subgroup] => 0 )
stdClass Object ( [name] => Jonas [type] => self [subgroup] => 3 [parent_subgroup] => 1 )
stdClass Object ( [name] => Leah [type] => sister [subgroup] => 3 [parent_subgroup] => 1 )
stdClass Object ( [name] => Jacob [type] => nephew [subgroup] => 4 [parent_subgroup] => 3 )
)
Постскриптум Нет, у меня и моей сестры не было ребенка. Это была просто моя аналогия, падающая на его лицо. 😉
RecursiveIterator
классы могут быть немного запутанными, мне нравится стараться сделать их простыми. Ты можешь использовать RecursiveIteratorIterator
чтобы перебрать значения вашего итератора, он может даже дать вам текущую глубину (или subgroup
в твоем случае).
Проблема в том, что родитель не является массивом, но мы можем позаботиться об этом в конструкторе.
<?php
class FamilyIterator implements RecursiveIterator{
private $data, $counter;
public function __construct($familyTree){
$this->data = is_array($familyTree) ? $familyTree : [$familyTree];
}
public function current(){
$row = $this->data[$this->counter];
return (object)[
'name' => $row->name,
'type' => $row->type
];
}
public function key(){
return $this->counter;
}
public function next(){
$this->counter++;
}
public function rewind(){
$this->counter = 0;
}
public function valid(){
return $this->counter < count($this->data);
}
public function hasChildren(){
$row = $this->data[$this->counter];
return isset($row->children);
}
public function getChildren(){
$row = $this->data[$this->counter];
return new self($row->children);
}
}
Тогда вы можете использовать этот класс как:
$loop = new RecursiveIteratorIterator(
new FamilyIterator($dataObj),
RecursiveIteratorIterator::SELF_FIRST
);
Когда ты foreach
над $loop
, он будет автоматически вызывать getChildren
метод, когда это необходимо, поэтому в foreach
у вас будет каждый ряд. Вы даже можете спросить RecursiveIteratorIterator
для глубины.
$newData = [];
foreach($loop as $row){
$row->subgroup = $loop->getDepth();
$newData[] = $row;
}
DEMO: https://eval.in/444078
Это не может быть именно так что вы хотели, но, надеюсь, это укажет вам правильное направление. RecursiveIterator
не должно быть сложным.
Других решений пока нет …