首页 > 解决方案 > Laravel Eloquent 按关系计数排序

问题描述

我有一个小型博客应用程序,允许用户上传照片和音频。用户还可以搜索其他博客。在搜索时,我想为我的查询添加一个排名,其优先级如下:

1) Users with most photos
2) Users with most audio

User模型构造如下:

public function blog() {
    return $this->hasOne(Blog::class);
}

public function photos() {
    return $this->hasMany(Photo::class);
}

public function audio() {
    return $this->hasMany(Audio::class);
}

博客模型是这样构建的:

public function user()
{
    return $this->belongsTo(User::class);
}

我当前的搜索查询:

    $blogs = Blog::where('description', 'ilike', '%'.$search.'%')
    ->orWhere('title', 'ilike', '%'.$search.'%')
    ->orWhereHas('user', function($query) use ($search) {
        $query->where('name', 'ilike', '%'.$search.'%')
            ->orWhere('username', 'ilike', '%'.$search.'%');
    })
    ->paginate(10);

根据给定的详细信息,我如何调整我的查询以返回对我的用户照片和音频计数进行排名的博客?

**更新**

我可以通过使用带有急切加载的withCount方法来获取每个嵌套关系的计数:

    $blogs = Blog::where('description', 'ilike', '%'.$search.'%')
    ->orWhere('title', 'ilike', '%'.$search.'%')
    ->orWhereHas('user', function($query) use ($search) {
        $query->where('name', 'ilike', '%'.$search.'%')
            ->orWhere('username', 'ilike', '%'.$search.'%');
    })
    ->with(['user' => function($query){
        $query->withCount(['blobs', 'audio']);
    }])
    ->paginate(10);

但是,我怎样才能通过那些嵌套的计数属性来排序这个当前查询呢?

标签: sqllaraveleloquentrelational-database

解决方案


基于 Laravel 8 文档: https ://laravel.com/docs/8.x/eloquent-relationships#counting-related-models

您可以尝试:

Blog::withCount(['photos', 'audio'])

它将放置 2 列:photos_count 和 audio_count。

所以最终的结果是:

$blogs = Blog::withCount(['photos', 'audio'])
->where('description', 'ilike', '%'.$search.'%')
->orWhere('title', 'ilike', '%'.$search.'%')
->orWhereHas('user', function($query) use ($search) {
    $query->where('name', 'ilike', '%'.$search.'%')
        ->orWhere('username', 'ilike', '%'.$search.'%');
})
->orderBy('photos_count', 'desc')
->orderBy('audio_count', 'desc')
->paginate(10);

推荐阅读