Laravel increment实现浏览量计数偶发多累加问题求助
Laravel increment浏览量异常累加问题排查及修复方案
问题原因
1. 作用域(Scope)使用不符合规范
Laravel的Scope设计初衷是复用查询构造逻辑,不应该在Scope中直接执行increment这类写操作。你当前的写法虽然大多数场景可以运行,但如果后续存在链式调用该Scope的场景,很容易触发重复执行计数逻辑的问题。
2. 浏览器预加载机制触发重复请求
现在主流浏览器都内置了链接预加载功能,用户hover到链接上时浏览器会提前发起请求预加载页面内容,如果用户随后正式点击访问,就会产生两次有效请求,导致浏览量累加2次。
3. 业务逻辑导致重复请求
可能的场景包括:
- 路由存在301/302重定向,跳转前后的两次请求都执行了计数逻辑
- 页面存在无效资源路径(如空src的img标签),错误触发了当前页面路由的请求
- 前端逻辑异常重复发起了页面请求
修复方案
第一步:修正模型方法定义
删掉原来的Scope写法,改为普通的模型实例方法:
// app/Models/Article.php public function incrementViewCount() { return $this->increment('view', 1); }
第二步:优化控制器计数逻辑,增加幂等判断
可以通过Session/Cookie标记用户访问状态,同一用户24小时内访问同一篇内容仅计数一次,同时排除浏览器预加载请求:
// 控制器逻辑 public function quoteBySlug($slug) { // 直接用firstOrFail简化404判断 $quote = Article::bySlug($slug)->firstOrFail(); // 排除浏览器预加载请求 $isPrefetch = request()->hasHeader('Purpose') && request()->header('Purpose') === 'prefetch' || request()->hasHeader('X-Moz') && request()->header('X-Moz') === 'prefetch'; // 验证用户是否已访问过该内容 $viewedKey = 'viewed_article_' . $quote->id; if (!$isPrefetch && !session()->has($viewedKey)) { $quote->incrementViewCount(); // 访问标记24小时内有效 session()->put($viewedKey, now()->timestamp); session()->expireAt($viewedKey, now()->addDay()); } return view('pages/quote/quote-detailed')->with('quote', $quote); }
第三步:排查业务侧异常
- 检查当前路由是否存在重定向配置
- 检查前端页面是否存在重复发起请求的逻辑,或者路径为空的资源标签
内容的提问来源于stack exchange,提问作者Bochorishvili Nikusha
相关产品推荐
相关产品推荐

