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

如何用Laravel Eloquent按根品牌标题对多对多关联产品排序?

我明白你的问题了——你想按产品关联的根品牌标题给产品排序,但用with()里的orderBy()只是给每个产品关联的品牌集合内部排序,根本不会影响产品列表本身的顺序,对吧?

刚好你用了laravel-nestedset包,这个包会自动给品牌表维护root_id字段(每个品牌的root_id都会指向它所属的根节点ID,根品牌自己的root_id就是自身ID),这正好可以帮我们快速实现需求。

最优解决方案(利用nestedset内置字段)

直接通过数据库join关联到根品牌,然后按根品牌标题排序,这样是在数据库层面完成排序,性能更好:

$products = Product::query()
    // 关联多对多中间表
    ->join('product_brand', 'products.id', '=', 'product_brand.product_id')
    // 关联品牌表,拿到每个关联品牌的root_id
    ->join('brands', 'product_brand.brand_id', '=', 'brands.id')
    // 通过root_id关联到根品牌表,获取根品牌的标题
    ->join('brands as root_brands', 'brands.root_id', '=', 'root_brands.id')
    // 选择产品的所有字段,避免重复数据
    ->select('products.*')
    // 分组去重:因为一个产品可能关联根+子品牌,会产生重复的产品记录
    ->groupBy('products.id')
    // 按根品牌标题降序排序
    ->orderBy('root_brands.title', 'desc')
    // 如果你需要加载产品关联的品牌集合,加上with
    ->with('brands')
    ->get();

替代方案(子查询方式)

如果你不想用join,也可以用子查询直接在排序逻辑里获取根品牌标题:

$products = Product::query()
    ->with('brands')
    ->orderByRaw('(
        SELECT title FROM brands 
        WHERE id = (SELECT root_id FROM brands WHERE id = product_brand.brand_id)
        LIMIT 1
    ) DESC')
    ->join('product_brand', 'products.id', '=', 'product_brand.product_id')
    ->groupBy('products.id')
    ->get();

为什么你之前的方法无效?

你之前写的:

$products_builder->with(['brands' => function($query) { 
    $query->orderBy('title', 'desc'); 
}]);

这段代码的作用仅仅是当加载每个产品的关联品牌时,给该产品的brands集合内部按标题排序,完全不会改变产品列表的整体顺序,所以才达不到按根品牌排序产品的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:47:45