对 Eloquent 个模型进行排序

Sort an Eloquent model

Table 对于 MyModel 如下所示

id      name        parent_id
--------------------------
1      parent1       null
2      p1-c1         1
3      parent2       null
4      p1-c1-g1      2
5      p2-c1         3
6      p1-c1-g1-f1   4
7      parent3       null
8      p1-c2         1
9      p3-c1         7
10     p1-c2-c1      8

如何使用 eloquent 或原始数据库查询进行排序,而不获取如下所示的所有行

Collection {#499 ▼
  #items: array:22 [▼
    0 => MyModel {#524 ▶} // parent1
    1 => MyModel {#525 ▶} // p1-c1
    2 => MyModel {#526 ▶} // p1-c1-g1
    3 => MyModel {#527 ▶} // p1-c1-g1-f1
    4 => MyModel {#528 ▶} // p1-c2
    5 => MyModel {#529 ▶} // p1-c2-c1
    6 => MyModel {#530 ▶} // parent2
    7 => MyModel {#531 ▶} // p2-c1
    8 => MyModel {#532 ▶} // parent3
    9 => MyModel {#533 ▶} // p3-c1
  ]
}

为了更好地查看和理解

parent1
p1-c1
p1-c1-g1
p1-c1-g1-f1
p1-c2
p1-c2-c1
parent2
p2-c1
parent3
p3-c1

使用相同的递归关系table

例如,如果型号名称是 MyModel,则关系将为

public function child(){
    return $this->hasMany(MyModel::class,'parent_id','id');
}

public function recursiveChild(){
    return $this->child()->with('recursiveChild');
}

所以在你的控制器中

MyModel::with(['recursiveChild'])->get();

你的实际代码是什么,你想用它完成什么? Collections 是你在 Laravel 的朋友。 如果你有一个相关的 table ,你可以做一个 groupBy 或使用 With ...你的问题真的太模棱两可了。 您可以通过限制和 groupBy 将许多链式 Where 或 Where 变得相当复杂 我所看到的是,您不仅需要数据库中的 parent,还需要对 children 进行排序。另一个想法是您需要 Grandparent、Parent、child 吗?在那种情况下,您将不得不为所有这些人提供列,以便在构建 collection 或直接 eloquent 拉动时知道他们属于谁。 我猜这是为了菜单或你这里有的东西。又是模棱两可,完全是瞎猜

编辑 我在几个应用程序中做过这种事情...... 你 table 看起来像这样:

id, name, menu_type, url, page_id, parent_id, sidebar, order, depth, role, created_at, updated_at, deleted_at

所以在你的模型中你想要建立关系:

  public function parent()
  {
      return $this->belongsTo('App\Models\Menus', 'parent_id');
  }

  public function children()
  {
      return $this->hasMany('App\Models\Menus', 'parent_id')->orderBy('order', 'asc');
  } 

然后我所做的就是将其用作特征,以便在我需要使用它的任何地方都可用。

该特征比您要求的要复杂一些,但它为您指明了方向。

 public function PrimaryMenu($pageid , $namespace, $user) {
        // Get all primary menu items.
        $appspace = "\App\Models\".$namespace."\Menus";
        $roles = $user->roles->pluck('name');
        $pmenus = $appspace::with('children')->where([['menu_type', '=', 'primary'],['parent_id','=', NULL]])->
        where(function ($q) use($pageid) {
            $q->where('page_id', '=', $pageid)->orWhere('page_id', NULL);
        })->
        where(function ($q2) use($roles) {
            $q2->whereIn('role', $roles)->orWhere('role', '=', NULL);
        })->
        get();

        return $pmenus;
    }

你可以看到我正在检查一种菜单类型(这可以是任何东西,只要你有东西可以按类别对它们进行分组)在这种情况下是主要的,然后我检查页面并看看我们是否应该包括一行或不在页面上,然后我检查用户可能拥有的任何角色,我们应该包括项目。

然后在您的控制器中,只需使用顶部的特征即可:

 use App\Traits\CommonTrait; 

现在所有这些特性都可以在您的控制器中使用。所以你只要调用你需要的函数:

$pmenus = $this->PrimaryMenu($pageid, $namespace, $user);

您可以看到我向此发送了 3 个变量,因为我已将其设置为具有多个菜单。实际上,代码可以转换为您希望 children 与 parent.

关联的任何内容

重要的部分是对关系的模型操作。

谢谢大家,我用这个包实现了这样的排序。

https://github.com/lazychaser/laravel-nestedset#building-flat-tree