簡體   English   中英

用於遞歸結果的 Laravel 查詢構建器? 例如 id、parent_id

[英]Laravel query builder for recursive results? E.g. id, parent_id

所以我的數據結構如下:

id|parent_id|name
1 |null     |foo
2 |1        |bar
3 |2        |baz

所以基本上foo->bar->baz 我很難過如何使用 laravel 的查詢構建器來獲取子行的行,然后是它的祖先(直到parent_id == null )。 這可以用laravel完成嗎? 我做了一些研究,Postgres 有RECURSIVE而 MySQL 沒有( Postgres 遞歸查詢在遍歷 parent_id 時更新字段的值)。

我相信 MySQL 有類似的東西: How to do the Recursive SELECT query in MySQL?

但是我將如何在 Laravel 中實現這一點?

我的起始代碼基本上是使用查詢范圍,但我只是沒有做對:

Model::select('name')->getParent(3); //get baz and the ancestors of baz
protected function scopeGetParent($id) {
  $parent = Model::where('id', '=', $id);
  return $query->getParent($parent->parent_id);
}

我想要的結果是:

name
baz
bar
foo

有任何想法嗎?

所以在擺弄Collections類的merge()方法之后:

public static function ancestors($id)
{
    $ancestors = Model::where('id', '=', $id)->get();

    while ($ancestors->last()->parent_id !== null)
    {
      $parent = Model::where('id', '=', $ancestors->last()->parent_id)->get();
      $ancestors = $ancestors->merge($parent);
    }

    return $ancestors;
}

這將產生我需要的東西,但是我相信它可以更干凈,所以請隨時編輯它!

我修改了tiffanyhwang解決方案並將其轉換為非靜態方法並包含一個屬性訪問器以更容易獲得結果。

public function ancestors()
{
    $ancestors = $this->where('id', '=', $this->parent_id)->get();

    while ($ancestors->last() && $ancestors->last()->parent_id !== null)
    {
        $parent = $this->where('id', '=', $ancestors->last()->parent_id)->get();
        $ancestors = $ancestors->merge($parent);
    }

    return $ancestors;
}

和訪問器從模型屬性中檢索祖先的集合

public function getAncestorsAttribute()
{
    return $this->ancestors();
    // or like this, if you want it the other way around
    // return $this->ancestors()->reverse();
}

所以現在你可以得到這樣的祖先:

$ancestors = $model->ancestors;

由於它是一個集合,您現在可以輕松地執行以下操作:

echo $model->ancestors->implode('title',', ');

另一種方法是使用etrepat/baum包,它是嵌套集模型的 Laravel 實現。 它使用更快的有序樹並使用非遞歸查詢。 雖然您的數據結構如下:

root
  |_ Child 1
    |_ Child 1.1
    |_ Child 1.2
  |_ Child 2
    |_ Child 2.1
    |_ Child 2.2

在嵌套集模型中有這樣的結構:

 ___________________________________________________________________
|  Root                                                             |
|    ____________________________    ____________________________   |
|   |  Child 1                  |   |  Child 2                  |   |
|   |   __________   _________  |   |   __________   _________  |   |
|   |  |  C 1.1  |  |  C 1.2 |  |   |  |  C 2.1  |  |  C 2.2 |  |   |
1   2  3_________4  5________6  7   8  9_________10 11_______12 13  14
|   |___________________________|   |___________________________|   |
|___________________________________________________________________|

插入節點很容易,因為:

$child1 = $root->children()->create(['name' => 'Child 1']);

我創建了一個使用公用表表達式 (CTE) 來實現遞歸關系的包: https : //github.com/staudenmeir/laravel-adjacency-list

您可以使用ancestors關系遞歸地獲取模型的所有父級:

class YourModel extends Model
{
    use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
}

$allParents = YourModel::find($id)->ancestors;

我修改了ruuter答案以使用關系。 如果模型上有 parent() 關系,則可以使用該關系刪除 where 子句,請參見下文:

public function parents()
{
        $parents = $this->parent()->get();

        while ($parents->last() && $parents->last()->parent_id !== null) {
                $parent = $parents->last()->parent()->get();
                $parents = $parents->merge($parent);
        }

        return $parents;
}

然后你可以訪問它:

public function allParents(): Collection 
{
        return $this->parents();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM