Laravel Получить предков (URL) - PullRequest
3 голосов
/ 11 марта 2019

В Laravel у меня есть таблица, которая содержит id, parent_id, slug (Self-ссылающийся),

Когда у меня есть идентификатор, мне нужно собрать всех его предков в таком формате (разделено "/").

level1/level2/level3

Но эффективно без пакета типа "laravel-nestedset" ».

Я реализовал это так.

public function parent()
{
    return $this->belongsTo('Collection', 'parent_id');
}

public function getParentsAttribute()
{
    $parents = collect([]);

    $parent = $this->parent;

    while(!is_null($parent)) {
        $parents->push($parent);
        $parent = $parent->parent;
    }

    return $parents;
}

Любой другой способ сделать это эффективно и разделенный "/"?

Ответы [ 2 ]

2 голосов
/ 11 марта 2019

После небольшого разговора в комментариях я думаю, что это хорошее решение:

// YourModel.php

// Add this line of you want the "parents" property to be populated all the time.
protected $appends = ['parents'];

public function getParentsAttribute()
{
    $collection = collect([]);
    $parent = $this->parent;
    while($parent) {
        $collection->push($parent);
        $parent = $parent->parent;
    }

    return $collection;
}

Затем вы можете найти своих родителей, используя:

Как отметил Николай Киселев https://stackoverflow.com/a/55103589/1346367 Вы также можете комбинировать это с этим, чтобы сохранить несколько запросов:

protected $with = ['parent.parent.parent'];
// or inline:
YourModel::find(123)->with(['parent.parent.parent']);

Это предварительно загружает родительский объект при загрузке объекта. Если вы решите не использовать это, родительский (загружается) загружается каккак только вы позвоните $yourModel->parent.

0 голосов
/ 11 марта 2019

Если вы знаете, сколько уровней может быть вложено, вы можете использовать Eager Loading.Скажем, если максимальная глубина составляет 3 уровня, вы можете сделать:

$model->with('parent.parent.parent');

Вы также можете использовать рекурсию вместо цикла.

public function getParentsAttribute()
{
    if (!$this->parent) {
        return collect([]);
    }

    return collect($this->parent->parents)->push($this->parent);
}

В случае, если вы тоже хотите добавить первый объект(само) полный вызов будет:

$model->parents->push($model)->reverse->implode('attr_name', '/');

, который вы также можете заключить в атрибут

public function getPathAttribute() {
    return $model->parents->push($model)->reverse->implode('attr_name', '/');
}

И позвонить как $model->path;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...