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

Laravel中查询各产品平均评分与评分总数的实现方法

Laravel 产品列表关联获取平均评分、评分总数实现方案

前置准备

首先确保Product模型中已经定义好和Review的一对多关联:

// app/Models/Product.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    // 其他原有模型配置
    public function reviews()
    {
        return $this->hasMany(Review::class, 'product_id');
    }
}

方案1:数据库层聚合查询(生产环境首选,性能最优)

利用Laravel原生的withCount方法自定义聚合字段,全程仅执行2条SQL,无N+1问题,不会加载多余评价数据,性能不受数据量影响。
首先在控制器头部引入DB门面:

use Illuminate\Support\Facades\DB;

查询代码如下:

$products = Product::withCount([
    // 统计评分总条数
    'reviews as review_total',
    // 计算平均评分,ROUND保留1位小数可按需调整,COALESCE处理无评价时默认返回0
    'reviews as avg_rating' => function ($query) {
        $query->select(DB::raw('ROUND(COALESCE(AVG(rating), 0), 1)'));
    }
])->get();

查询结果直接通过对象属性调用即可:

foreach ($products as $product) {
    // 原有产品字段
    $product->id;
    $product->name;
    $product->price;
    // 新增统计字段
    $product->review_total; // 该产品评分总条数
    $product->avg_rating; // 该产品平均评分
}

方案2:集合层计算(仅适合小数据量场景)

如果项目评价总量很小,可以预加载关联后通过Laravel集合方法计算统计值,缺点是会查询出所有关联的评价记录,数据量大时内存占用极高,不推荐生产环境大数据量场景使用:

$products = Product::with('reviews')
    ->get()
    ->map(function ($product) {
        $product->review_total = $product->reviews->count();
        $product->avg_rating = $product->reviews->avg('rating') ?? 0;
        return $product;
    });

避坑提示

不要在未预加载关联的情况下,循环遍历产品时单独查询评价统计:

// 错误写法,会产生N+1查询,产品数量越多SQL执行次数越多,性能极差
$products = Product::all();
foreach ($products as $product) {
    $product->review_total = $product->reviews()->count();
    $product->avg_rating = $product->reviews()->avg('rating');
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:57:33