You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何让withAggregate关联查询按指定顺序排序?

解决Laravel withAggregate忽略关联排序的问题

问题场景

使用withAggregate做关联聚合查询时,即便在HasOne关联里定义了orderBy规则,生成的子查询依然不会带上排序,导致只能拿到关联表的最早记录。

原查询代码:

$users = \App\Models\User::withAggregate('lastactivity', 'created_at')
    ->orderBy('id', 'DESC')
    ->paginate(15);

生成的SQL(缺少关联排序):

select `users`.*, (select created_at from `users_activity` where `users`.`id` = `users_activity`.`user_id` limit 1) as `lastactivity_created_at` from `users` order by `id` desc limit 15 offset 0

期望生成的SQL(包含关联降序排序):

select `users`.*, (select created_at from `users_activity` where `users`.`id` = `users_activity`.`user_id` order by id desc limit 1) as `lastactivity_created_at` from `users` order by `id` desc limit 15 offset 0

关联关系定义:

public function lastactivity(): HasOne
{
    return $this->hasOne(UsersActivity::class)->orderBy('id', 'DESC');
}

解决方法

直接在withAggregate中传入闭包,手动指定子查询的排序规则:

$users = \App\Models\User::withAggregate('lastactivity', function ($query) {
    $query->select('created_at')->orderBy('id', 'DESC');
})->orderBy('id', 'DESC')->paginate(15);

原因说明

withAggregate在构建聚合子查询时,不会完全复用关联定义里的所有约束(比如排序),而是会生成一个简化的查询实例。因此必须通过闭包显式传入排序规则,才能确保子查询按要求获取最新的关联记录。

复用优化方案

如果需要在多处使用这个逻辑,可以在模型里单独定义一个带排序的聚合关联方法:

public function latestActivity()
{
    return $this->hasOne(UsersActivity::class)
        ->select('user_id', 'created_at')
        ->orderBy('id', 'DESC');
}

之后调用withAggregate时直接用这个方法:

$users = \App\Models\User::withAggregate('latestActivity', 'created_at')
    ->orderBy('id', 'DESC')
    ->paginate(15);

内容的提问来源于stack exchange,提问作者Linesofcode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:08:24