如何在Laravel中实现分享按钮并获取每篇文章的分享次数?
Laravel 实现带分享次数统计的分享按钮教程
1. 数据表结构调整
首先根据业务需求选适合的存储方案:
- 方案1(轻量统计需求):直接给文章表加分享次数字段,无需额外关联表
执行迁移生成命令:php artisan make:migration add_share_count_to_posts_table --table=posts
编辑生成的迁移文件:
执行迁移生效:public function up() { Schema::table('posts', function (Blueprint $table) { $table->unsignedInteger('share_count')->default(0)->comment('文章分享次数'); }); }php artisan migrate - 方案2(明细统计需求):单独创建分享记录表,可记录分享用户、分享渠道、分享时间等信息,字段可按需设置
user_id、post_id、channel、ip等,后续统计次数直接关联表计数即可。
2. 后端统计接口开发
先添加路由,在routes/web.php中新增:
Route::post('/posts/{post}/share', [\App\Http\Controllers\PostController::class, 'share'])->name('posts.share');
在PostController中实现统计逻辑:
public function share(\App\Models\Post $post, \Illuminate\Http\Request $request) { // 防重复刷逻辑:可按IP、用户ID做频次限制,比如24小时内同个用户同篇文章仅算1次分享 $exists = \App\Models\Share::where('post_id', $post->id) ->when(auth()->check(), fn($q) => $q->where('user_id', auth()->id())) ->when(!auth()->check(), fn($q) => $q->where('ip', $request->ip())) ->where('created_at', '>=', now()->subDay()) ->exists(); if (!$exists) { // 方案1:直接累加字段 $post->increment('share_count'); // 方案2:新增分享记录,后续次数用 $post->shares()->count() 获取即可 // \App\Models\Share::create([ // 'post_id' => $post->id, // 'user_id' => auth()->id(), // 'channel' => $request->input('channel'), // 'ip' => $request->ip() // ]); } return response()->json([ 'code' => 0, 'share_count' => $post->share_count ]); }
如果项目访问量较大,建议把分享次数先存到Redis做增量,定时异步同步到数据库,降低数据库写入压力。
3. 前端分享按钮实现
Blade模板部分示例:
<meta name="csrf-token" content="{{ csrf_token() }}"> <div class="share-group"> <button class="share-item" data-channel="weibo">分享到微博</button> <button class="share-item" data-channel="wechat">分享到微信</button> <button class="share-item" data-channel="qq">分享到QQ</button> <div>分享次数:<span id="share-num">{{ $post->share_count }}</span></div> </div>
JS交互逻辑示例:
document.querySelectorAll('.share-item').forEach(btn => { btn.addEventListener('click', async function() { const channel = this.dataset.channel; // 先调用统计接口上报分享行为 const res = await fetch(`/posts/{{ $post->id }}/share`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify({channel: channel}) }); const data = await res.json(); // 更新页面展示的分享次数 document.querySelector('#share-num').textContent = data.share_count; // 后续执行对应渠道的分享逻辑: // 普通H5渠道直接按官方规则拼接分享参数跳转即可 // 微信生态内可调用微信JSSDK实现原生分享 // 端内分享可调用客户端提供的分享能力 }) })
4. 分享次数获取
- 后端接口返回:直接将
share_count字段加入接口返回参数即可,用方案2的话可通过关联关系预加载统计避免N+1问题 - 前端页面渲染:Blade模板直接输出
{{ $post->share_count }}即可
注意:分享统计逻辑要放在分享行为触发的第一时间执行,不要等分享成功回调再统计,多数第三方分享渠道不会返回明确的成功状态,提前统计的偏差率在可接受范围内。
内容的提问来源于stack exchange,提问作者basic
相关产品推荐
相关产品推荐

