Laravel 怎么通过关联字段排序?

表 users:

字段 id
字段 group_id

表 groups:

字段 id
字段 family_id

两个模型已经定义了模型关联

现在要将取出的 user模型 按照 family_id 排序

$users = User::with(['group' => function ($query) {
                $query->orderBy('family_id', 'asc');
            }])->get();

这种情况好像并不好使

以上是在网上找到的例子,编码时候也遇到这种情况应该如何解决?求大神指点一下

meitesi
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

你想一想,laravel关联模型是怎么实现的?它没有使用join而是直接拆分成两条SQL,后一条SQL的结果集基于前一条SQL的结果集的id集,那么如果你想按照哪个字段排序就是用那个字段所在的表关联另外的表,如果要跨表两个字段分别排序,是否可以考虑一下冗余字段,实在不行就可以考虑一下join是否满足需求。

6年前 评论
讨论数量: 5

你想一想,laravel关联模型是怎么实现的?它没有使用join而是直接拆分成两条SQL,后一条SQL的结果集基于前一条SQL的结果集的id集,那么如果你想按照哪个字段排序就是用那个字段所在的表关联另外的表,如果要跨表两个字段分别排序,是否可以考虑一下冗余字段,实在不行就可以考虑一下join是否满足需求。

6年前 评论

直接在User模型中定义Goup关联的时候如下

public function group()
{
    return $this->hasMany(User::class)->orderBy('id')
}
4年前 评论

你想一想,laravel关联模型是怎么实现的?它没有使用join而是直接拆分成两条SQL,后一条SQL的结果集基于前一条SQL的结果集的id集,那么如果你想按照哪个字段排序就是用那个字段所在的表关联另外的表,如果要跨表两个字段分别排序,是否可以考虑一下冗余字段,实在不行就可以考虑一下join是否满足需求。

6年前 评论

直接在User模型中定义Goup关联的时候如下

public function group()
{
    return $this->hasMany(User::class)->orderBy('id')
}
4年前 评论

怎么说呢…
A表 :

id name
1 法外狂徒-张三
2 不要碧莲-张楚岚

B表:

id aid source
1 2 《一人之下》
2 1 《厚大法考》

场景/方案 1. 直接将B表作为主表关联A表进行查询

B::query()
   ->with(['A'])
   ->orderBy('aid')
   ->limit($pagesize)
   ->get();

场景/方案 2. 根据业务场景、数据量来判断使用何种方式
数据量小无所谓,两种都行,如果仅仅是跨表排序,可以使用sortBy、sortByDesc

$resultA = A::query()
   ->with(['B'])
   ->orderBy('B.aid')
   ->limit($pagesize)
   ->get();
$sortedResult = $resultA->sortBy('B.aid')->get()

例如:但是如果使用A模型,需要对B.aid进行排序,然后分页查询呢?with查询的时候orderBy?

A::query()
   ->with(['B'])
   ->orderBy('B.aid')
   ->limit($pagesize)
   ->get();
   难道要这样写吗?答案是不行

因为这样写会给你报下面这样的错误。

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'B.aid' in 'order clause' 

具体错误原因,上面错误已经说了:未知列。
打印一下SQL就会发现了,下面这个sql里根本不存在B表关联。当然是未知列了。

select * from `A` where `A`.`deleted_at` is null order by `B`.`aid` asc limit 5

像一楼说的,从人家本质的SQL原理入手找问题的答案,laravel:with

file
这种”跨表排序还要分页“的操作就不能使用with,只能使用冗余字段或者是join查询了。

3年前 评论

自己写了一个简单的Builder marco可以参考下

// 基于关联关系排序实现
Builder::macro('orderByWith', 
    function ($relation, $column, $direction = 'asc'): Builder{
            /** @var Builder $this */
            if (is_string($relation)) {
                $relation = $this->getRelationWithoutConstraints($relation);
            }

            return $this->orderBy(
                $relation->getRelationExistenceQuery(
                    $relation->getRelated()->newQueryWithoutRelationships(),
                    $this,
                    $column
                ),
                $direction
            );
        });

调用如下

$products = Product::has('cates') // 基于当前分类关联
            // 根据分类关联中的sort字段进行排序
            ->orderByWith('cates','sort','desc')
            ->paginate($limit);
3年前 评论

了解一下order by field

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!