按关系列排序

The*_*eal 14 laravel eloquent

我有以下查询:

$items = UserItems::with('item')
        ->where('user_id','=',$this->id)
        ->where('quantity','>',0)
        ->get();
Run Code Online (Sandbox Code Playgroud)

我需要按item.type订购它,所以我试过:

$items = UserItems::with('item')
        ->where('user_id','=',$this->id)
        ->where('quantity','>',0)
        ->orderBy('item.type')
        ->get();
Run Code Online (Sandbox Code Playgroud)

但我明白了 Unknown column 'item.type' in 'order clause'

我错过了什么?

Ras*_*id 33

您可以使用 withAggregate('relationship', 'column') 函数。

它为 UserItems 实例创建一个“item_type”属性,然后您可以使用 orderBy('item_type') 来定位该属性。它也可以与分页
一起使用,如 limit()、skip() 等,因为它在数据库调用后不使用 sortBy()。

UserItems::withAggregate('item','type')
    ->where('user_id','=',$this->id)
    ->where('quantity','>',0)
    ->orderBy('item_type')
    ->get();
Run Code Online (Sandbox Code Playgroud)

这样,您仍然可以在 Eloquent 查询中使用关系并对集合进行排序,而无需进行联接或 orderByRaw() 调用。

  • 这应该被接受的答案 (2认同)

The*_*eal 13

由于@rypskar评论,join()工作得很好

$items = UserItems
        ::where('user_id','=',$this->id)
        ->where('quantity','>',0)
        ->join('items', 'items.id', '=', 'user_items.item_id')
        ->orderBy('items.type')
        ->select('user_items.*') //see PS:
        ->get();
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您希望连接模型作为结果的一部分返回,您仍然可以照常使用 `with`。在这个例子中,`->with('item')`。 (5认同)

Rep*_*pox 8

好吧,您的急切加载可能无法构建您期望的查询,您可以通过启用查询日志来检查它.

但我可能只是使用集合过滤器:

$items = UserItems::where('user_id','=',$this->id)
        ->where('quantity','>',0)
        ->get()
        ->sortBy(function($useritem, $key) {
          return $useritem->item->type;
        });
Run Code Online (Sandbox Code Playgroud)

  • 对于那些使用`skip`和`limit`做**分页**的人,这会导致错误的结果。 (9认同)
  • @TheUnreal 你需要在 ->sortBy() 之后调用 ->values() (2认同)
  • 排序值的简写是 - > sortBy('item.type') (2认同)

小智 6

我知道这是一个老问题,但您仍然可以使用“orderByRaw”而不需要连接。

$items = UserItems
        ::where('user_id','=',$this->id)
        ->where('quantity','>',0)
        ->orderByRaw('(SELECT type FROM items WHERE items.id = user_items.item_id)')
        ->get();  
Run Code Online (Sandbox Code Playgroud)