Laravel + Vue 如何基于eloquent-viewable实现文章访问量统计
可落地方案说明
你之前用的eloquent-viewable包完全适配Laravel+Vue的前后端分离架构,不需要完全重写计数逻辑,只需要调整触发计数的时机即可,整体改造成本非常低。
1. 复用原有包的基础配置
- 之前在纯Laravel项目里配好的内容全部保留:Article模型引入的
Viewabletrait、views表的数据库结构、$article->views()的查询逻辑都不需要改动 - 移除
app/Http/Kernel.php中挂在全局路由组下、由eloquent-viewable包提供的自动记录中间件——这个中间件原本是给服务端渲染场景用的,前后端分离场景下如果不删掉,会导致列表请求、鉴权请求等非文章详情的接口访问都被误计为文章浏览量,数据完全失真
注意:如果之前项目里开启了包的IP/Session去重规则,需要给前端的axios实例配置
withCredentials: true,让跨域请求能正常携带Laravel的Session Cookie,否则去重逻辑会失效,同一用户每次打开文章都会被计为新的访问。
2. 后端新增独立的访问上报接口
不要把计数逻辑混在文章详情的GET查询接口里,否则会出现前端命中浏览器缓存、或者预取资源时根本不发GET请求导致的漏计数问题。
- 在
routes/api.php中新增独立的POST上报路由,搭配Laravel自带的限流中间件防止刷量:
use App\Http\Controllers\ArticleController; Route::post('/articles/{article}/increment-view', [ArticleController::class, 'incrementView']) ->middleware('throttle:10,1');
- 对应控制器的方法逻辑非常简单,直接调用
eloquent-viewable包自带的记录方法即可:
public function incrementView(Article $article) { // 自动处理去重、访问来源记录,和纯Laravel项目里的逻辑完全一致 $article->view(); return response()->json([ 'code' => 0, 'data' => [ 'total_views' => $article->views() ] ]); }
为什么要单独拆接口?因为GET类的详情接口很容易被浏览器、CDN、前端预取逻辑缓存,把计数逻辑放在这里会出现计数不准的问题;独立的POST接口不会被缓存,能保证计数触发的准确性。
3. 前端Vue端接入触发逻辑
- 直接在文章详情页的组件生命周期钩子中调用上报接口即可,不要阻塞页面主渲染流程:
// Vue3 示例代码 import { onMounted } from 'vue' import axios from 'axios' const props = defineProps({ articleId: Number }) onMounted(() => { // 异步上报,不影响页面加载速度 axios.post(`/api/articles/${props.articleId}/increment-view`) })
- 可选优化:如果站点用户量大,可以把axios请求替换为
navigator.sendBeacon发送上报,这个方法专门用于埋点场景,就算用户中途路由跳转、关闭页面,请求也能稳定送达,不会被浏览器主动取消:
// 替换axios调用为sendBeacon navigator.sendBeacon(`/api/articles/${props.articleId}/increment-view`)
- 可以搭配本地
SessionStorage做简单的会话级去重:同一个用户在同一次浏览会话里反复打开同一篇文章,不重复发上报请求,减少无效接口压力。
极简替代方案(不想依赖第三方包时)
如果你的计数逻辑不需要去重、不需要记录访问来源,只需要简单的累加计数:
- 给
articles表加一个views_count无符号整数字段,默认值为0 - 上报接口的逻辑直接改成:
public function incrementView(Article $article) { Article::where('id', $article->id)->increment('views_count'); return response()->json(['code' => 0, 'data' => ['total_views' => $article->views_count]]); }
这种方案没有任何第三方依赖,逻辑更简单,只是缺少包自带的精细化统计能力,适合需求非常简单的小型站点。
内容的提问来源于stack exchange,提问作者Jad es
相关产品推荐
相关产品推荐

