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

Laravel Eloquent如何按自定义total_views属性对Product模型查询结果排序

问题原因说明

Laravel 的访问器是在SQL查询完成、模型实例化之后才会生成的属性,orderBy 属于SQL查询阶段的操作,数据库层面根本不存在 total_views 这个字段,所以直接用访问器属性做排序不会生效。同时你原本的访问器实现会存在N+1查询问题,列表查询时每个商品实例都会单独触发一次求和查询,性能很差。


方案1:使用 withCount 实现SQL层面排序(通用推荐)

这是性能最优的通用方案,兼容分页需求,一次查询即可完成所有统计和排序:

use Illuminate\Support\Facades\DB;

$products = Product::withCount([
    'views as total_views' => function ($query) {
        // 统计关联views表count字段的和,IFNULL处理无浏览记录时返回0
        $query->select(DB::raw('IFNULL(SUM(count), 0)'));
    }
])
// 直接对SQL计算出的total_views字段排序
->orderBy('total_views', 'desc')
->get();

方案2:集合排序(仅适合极小数据量场景)

如果你的商品总数据量小于100条且不需要分页,可以查询出全量数据后用Laravel集合方法排序:

// 查询所有商品后在PHP层面按访问器属性排序
$products = Product::get()->sortByDesc('total_views');

注意该方案缺陷明显:需要将全量数据加载到内存中排序,数据量稍大就会出现性能问题,且无法正常使用分页功能。

方案3:冗余字段优化(高频排序场景推荐)

如果业务中需要频繁按总浏览量排序,建议在products表新增total_views整型字段,通过模型事件/观察者在View模型的新增、更新事件触发时,同步更新对应商品的total_views值,后续排序直接操作实际字段即可,性能最高:

// 排序逻辑简单,查询效率远高于关联统计
$products = Product::orderBy('total_views', 'desc')->paginate(10);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:36:02