Истина действительно находится посередине: когда вы не возвращаете значение рекурсивного вызова, вы теряете собранную вами информацию. Когда, с другой стороны, вы возвращаете значение рекурсивного вызова, оно не будет работать, потому что вы тогда всегда вернитесь на первой итерации вашего цикла foreach
.
Итак, вам нужно иногда возвращать его: только когда вы имели совпадение в рекурсивной части. Если нет успеха, вы не должны вернуться и продолжить foreach
цикл:
public function getChildById($root, $id){
if (!empty($root->nodes)){
foreach ($root->nodes as $node){
if ($node->getId()==$id){
return $node;
} else {
$found = $this->getChildById($node, $id);
if ($found) return $found;
}
}
}
}
Посмотреть работать на eval.in.
Обратите внимание, что чаще всего проводится проверка соответствия для корня, поэтому в начале функции. Это сводится к тому же, за исключением того, что если значение находится на самом корне, с которым вы вызываете функцию, оно также найдено!
public function getChildById($root, $id){
if ($root->getId()==$id) return $root;
foreach ($root->nodes as $node){
$found = $this->getChildById($node, $id);
if ($found) return $found;
}
}
Вы не фиксируете возвращаемое значение своего рекурсивного вызова. и не имеют возможности сигнализировать о неудачном поиске (например, когда вы достигаете узла 13, вы должны вернуть SOMETHING, чтобы сигнализировать, что ничего не найдено (и ничего не найдено) в этой ветке, так что «родительские» вызовы будут знать, чтобы двигаться дальше к следующему родному узлу. –