如何在 Laravel 中高效获取每个商品的平均评分与评分总数

花韻仙語

花韻仙語

2026-07-20

1021人浏览

原创

如何在 Laravel 中高效获取每个商品的平均评分与评分总数

本文介绍在 laravel 中通过 eloquent 和 query builder 两种方式,为每个商品关联计算平均评分(avg)和评分总数(count),并确保空评分商品也能正确显示为 0。

本文介绍在 laravel 中通过 eloquent 和 query builder 两种方式,为每个商品关联计算平均评分(avg)和评分总数(count),并确保空评分商品也能正确显示为 0。

在构建电商或内容平台的商品评价系统时,常需同时展示商品列表及其对应的用户评分统计——包括平均分(保留小数)与总评分人数。Laravel 提供了灵活的数据聚合能力,可通过关系查询或原生联表高效实现该需求,无需对每个商品发起 N+1 查询。

✅ 推荐方案:使用 leftJoin + 聚合函数(兼顾性能与完整性)

最高效的方式是利用数据库层面的 LEFT JOIN,将 products 表与 reviews 表关联,并对每个商品一次性计算 AVG() 与 COUNT()。关键点在于使用 LEFT JOIN(而非 INNER JOIN),以确保即使某商品暂无任何评价,仍能出现在结果中,且其评分字段可设为默认值(如 0):

use Illuminate\Support\Facades\DB;

$products = DB::table('products')
    ->leftJoin('reviews', 'reviews.product_id', '=', 'products.id')
    ->select(
        'products.*',
        DB::raw('COALESCE(AVG(reviews.rating), 0) as average_rating'),
        DB::raw('COUNT(reviews.id) as rating_count')
    )
    ->groupBy('products.id') // 必须按主键分组,否则报错
    ->get();

⚠️ 注意事项:

  • GROUP BY products.id 不可省略,否则聚合函数会作用于整个结果集;
  • COALESCE(AVG(...), 0) 确保无评价的商品 average_rating 返回 0.0(而非 null);
  • COUNT(reviews.id) 统计的是匹配到的 review 记录数,自动忽略 NULL(即未关联 review 的行),天然满足“零评分”场景。

✅ 进阶方案:基于 Eloquent 模型关系(更面向对象)

若已定义 Eloquent 模型及关联关系,推荐在 Product 模型中定义 ratings 关系,并使用 withCount() 与 withAvg()(Laravel 8.35+ 支持):

Laravel 13.2.0
Laravel 13.2.0

PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。

下载
// 在 Product.php 模型中
public function ratings()
{
    return $this->hasMany(Review::class, 'product_id');
}

然后在控制器中调用:

use App\Models\Product;

$products = Product::withCount('ratings')
    ->withAvg('ratings', 'rating')
    ->get()
    ->map(function ($product) {
        return $product->merge([
            'average_rating' => round($product->ratings_avg_rating, 2),
            'rating_count' => $product->ratings_count,
        ]);
    });

此方式语义清晰、易于测试,且支持后续链式扩展(如添加 whereHas() 等条件)。但注意:withAvg() 返回的是 float|null,建议用 round() 格式化小数位,并用 ?? 0 处理空值(或如上例在 map() 中统一处理)。

? 验证与调试提示

  • 使用 dd($products->toArray()) 查看原始结构,确认 average_rating 与 rating_count 字段存在且类型正确;
  • 若遇到 SQLSTATE[42000] 分组错误,请检查是否遗漏 groupBy() 或 SELECT 中包含未聚合/未分组的非主键字段;
  • 生产环境建议为 reviews.product_id 添加数据库索引,大幅提升联表性能:
    ALTER TABLE reviews ADD INDEX idx_product_id (product_id);

综上,联表聚合(Query Builder)适合高性能批量统计,Eloquent 关系聚合则更利于代码可维护性。根据项目复杂度与团队规范选择即可——两者均能优雅解决“每个商品的平均分与评分总数”这一核心需求。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

5433

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

3588

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

1786

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

2272

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

2783

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

1999

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

3030

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

2312

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

10929

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何安装 Composer
如何安装 Composer

共1课时 | 128人学习

Composer手册
Composer手册

共0课时 | 0人学习