【问题标题】:Order by relationship column按关系列排序
【发布时间】:2016-11-10 17:18:12
【问题描述】:

我有以下疑问:

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

我需要按 item.type 订购,所以我尝试了:

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

但我得到Unknown column 'item.type' in 'order clause'

我错过了什么?

【问题讨论】:

  • 你的表是命名为item还是items?我的猜测是你的关系被称为 item 但表格是 items 所以它应该是orderBy('items.type')
  • 我都试过Column not found: 1054 Unknown column 'items.type' in 'order clause'
  • 看你的查询日志,你的主查询和关系是分开的,没有交叉。您可能需要进行某种类型的连接才能按这样的另一个表排序。
  • 这可能是因为with() 正在使用急切加载,这会将其变成两个查询。尝试使用join() 而不是with()

标签: laravel eloquent


【解决方案1】:

嗯,您的预加载可能没有构建您期望的查询,您可以通过启用查询日志来检查它。

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

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

【讨论】:

  • 由于某些原因,返回的数据是一个对象而不是一个对象数组,比如返回的和原始查询
  • @TheUnreal 你需要在 ->sortBy() 之后调用 ->values()
  • 对一个值进行排序的简写是 ->sortBy('item.type')
  • 这会对内存中获取的集合项进行排序。如果你想对你的数据库表进行排序操作,你应该在 get() 方法之前调用 sortBy。
  • 对于那些使用skiplimit进行分页的人,这会导致错误的结果。
【解决方案2】:

由于@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();

PS:为避免id 属性(或两个表之间的任何共享名称属性)重叠并导致错误值,您应该使用select('user_items.*') 指定选择限制。

【讨论】:

  • 请注意,如果您希望连接的模型作为结果的一部分返回,您仍然可以照常使用with。在此示例中,->with('item').
  • 这不适用于变形关系:( @Repox 答案更好
【解决方案3】:

我找到了另一种使用相关模型中的字段对数据集进行排序的方法,您可以在模型中获取与相关表具有唯一关系的函数(例如:与房间类别相关的表房间,房间是通过类别 id 与类别相关,您可以使用像“room_category”这样的函数,它根据房间模型的类别 id 返回相关类别),之后代码如下:

Room::with('room_category')->all()->sortBy('room_category.name',SORT_REGULAR,false);

这将为您提供按类别名称排序的房间

我在一个项目中执行此操作,其中我有一个带有服务器端处理的 DataTable,并且我有一个案例需要按相关实体的字段进行排序,我这样做了并且它有效。更简单,更符合 MVC 标准。

在您的情况下,它将采用类似的方式:

User::with('item')->where('quantity','>',0)->get()->sortBy('item.type',SORT_REGULAR,false);

【讨论】:

  • 请注意,这会将所有内容作为集合返回,然后对其进行排序,如果您有大型数据集,这可能是个问题
【解决方案4】:

一个简单的方法...

$items = UserItems::with('item')
        ->where('user_id','=',$this->id)
        ->where('quantity','>',0)
        ->get()->sortBy('item.type');

【讨论】:

  • 您的答案可以通过添加有关代码的作用以及它如何帮助 OP 的更多信息来改进。
猜你喜欢
  • 2016-06-21
  • 1970-01-01
  • 2014-06-25
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
相关资源
最近更新 更多