我有以下疑问:
$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'
我缺少什么?
@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.*')
指定选择限制。
您可以使用 withAggregate('relationship', 'column') 函数。
它为 UserItems 实例创建一个“item_type”属性,然后您可以使用 orderBy('item_type') 来定位该属性。
它也可以与 pagination 一起使用,如 limit()、skip() 等,因为它在数据库调用后不使用 sortBy()。
UserItems::withAggregate('item','type')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->orderBy('item_type')
->get();
这样,您仍然可以在雄辩的查询中使用关系并对集合进行排序,而无需进行联接或 orderByRaw() 调用。
生成的查询将类似于:
select `users`.*, (select type from `items` where `items`.`user_id` = `users`.`id` limit 1) as `item_type` from `users` where `users`.`id` = 123 AND `users`.`quantity` > 0 order by item_type asc)
嗯,您的急切加载可能没有构建您期望的查询,您可以通过启用查询日志来检查它。
但我可能只使用集合过滤器:
$items = UserItems::where('user_id','=',$this->id)
->where('quantity','>',0)
->get()
->sortBy(function($useritem, $key) {
return $useritem->item->type;
});
我知道这是一个老问题,但你仍然可以使用 没有连接的“orderByRaw”。
$items = UserItems
::where('user_id','=',$this->id)
->where('quantity','>',0)
->orderByRaw('(SELECT type FROM items WHERE items.id = user_items.item_id)')
->get();
对于一对多关系,有一种更简单的方法。假设一个订单有很多付款,我们希望按最新付款日期对订单进行排序。 Payments 表有一个名为 order_id 的字段,它是 FK。
我们可以像下面这样写
$orders = Order->orderByDesc(Payment::select('payments.date')->whereColumn('payments.order_id', 'orders.id')->latest()->take(1))->get()
此代码的 SQL 等效项:
select * from orders order by (
select date
from payments
where order_id = payments.id
order by date desc
limit 1
) desc
您可以根据您的示例进行调整。如果我理解正确的话,在您的情况下,订单的等价物是用户,付款的等价物是项目。
进一步阅读
https://reinink.ca/articles/ordering-database-queries-by-relationship-columns-in-laravel
你可以简单地做到这一点
UserItems::with('item')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->orderBy(
Item::select('type')
->whereColumn('items.useritem_id','useritems.id')
->take(1),'desc'
)
->get();
$items = UserItems::with('item')
->where('user_id','=',$this->id)
->where('quantity','>',0)
->with(['item' => function($q) {
$q->orderBy('type', 'asc');
]})
->get();
将关系数组传递给“with”方法,其中:
我找到了另一种使用相关模型中的字段对数据集进行排序的方法,您可以在模型中获取一个函数,该函数获取与相关表的唯一关系(例如:房间与房间类别相关,房间与按类别 id 划分的类别,您可以使用像“room_category”这样的函数,它根据房间模型的类别 id 返回相关类别),之后的代码如下:
Room::with('room_category')->all()->sortBy('room_category.name',SORT_REGULAR,false);
这将为您提供按类别名称排序的房间
我在一个项目中执行了此操作,其中我有一个带有服务器端处理的数据表,并且我遇到了需要按相关实体的字段进行排序的情况,我这样做了并且它有效。更简单,更符合 MVC 标准。
在你的情况下,它会以类似的方式:
User::with('item')->where('quantity','>',0)->get()->sortBy('item.type',SORT_REGULAR,false);
$users
->whereRole($role)
->join('address', 'users.id', '=', 'address.user_id')
->orderByRaw("address.email $sortType")
->select('users.*')