Рекурсивное самостоятельное присоединение Laravel - PullRequest
0 голосов
/ 05 августа 2020

У меня есть следующая таблица:

| node_id | node_name | parent_id |  
| 1       | Node 1    |           |  
| 2       | Node 2    | 1         |  
| 3       | Node 3    | 1         |  
| 4       | Node 4    | 2         |

Я хочу рекурсивно получить все узлы под определенным c узлом.

Моя модель выглядит так:

class Tree extends Model
{
    public function parent()
    {
        return $this->belongsTo(self::class, 'node_id');
    }

    public function children()
    {
        return $this->hasMany(self::class, 'parent_id', 'node_id');
    }

    public function allchildren()
    {
        return $this->hasMany(self::class, 'parent_id', 'node_id')->with('allchildren');;
    }
}

Теперь, если я хочу получить всех потомков узла, я делаю следующее:

$node = Tree::where('node_id', 1)->first();
$nodes = $node->allchildren;
        

Однако приведенный выше код возвращает только первый уровень и игнорирует более глубокие дочерние уровни.

Что я здесь делаю не так?

Edit

На самом деле, теперь я понимаю, что я действительно получаю все данные правильно, это просто я вижу верхний уровень выходного массива.

Возникает вопрос, как я могу сгладить выходные данные, чтобы показать мне данные в одном массиве?

Редактировать 2

Итак, мне удалось создать функцию для сглаживания вывода в одноуровневый массив, используя следующий код (например, в контроллере):

public function flattenTree($array)
{
    $result = [];
    foreach ($array as $item) {
        $result[] = ['node_id'=>$item['node_id'], 'node_name'=>$item['node_name']];
        $result = array_merge($result, $this->flattenTree($item['allchildren']));
    }
    return array_filter($result);
}

, а затем вызвать это так:

$flatTree = $this->flattenTree($nodes);

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Вы можете выполнить нетерпеливую загрузку , используя with(). Таким образом, это будет выглядеть как

Tree::where('node_id', 1)->with('allchildren')->get();

Вы могли бы также go вложить нетерпеливую загрузку.

Tree::where('node_id', 1)->with('children.children')->get();
0 голосов
/ 05 августа 2020

Сверху в голове, я думаю, вы могли бы добиться этого с помощью чего-то вроде этого. создать новую коллекцию узлов. Обратной стороной этого конкретного logi c является то, что он получит все узлы в одноуровневой коллекции.

...