Laravel中如何通过Ajax持续存储视频播放进度至数据库?
嘿,我来帮你一步步搞定这个视频续看功能!你已经搭好了监听播放状态、获取播放时长的基础代码,接下来只需要把这些数据通过Ajax传给Laravel后端,再更新到users表的watch_history字段就行。下面是具体实现步骤:
一、前端代码修改(Lesson_video.blade.php)
首先要把Blade里的lesson_id传给JS,然后在你的performaction函数里加入Ajax请求,把数据发给后端:
<!-- 先确保你的页面<head>里有CSRF令牌(Laravel默认模板一般已经包含,没有的话加上) --> <meta name="csrf-token" content="{{ csrf_token() }}"> <script> var vid = document.getElementById("player"); // 从Blade模板获取当前课程ID let lessonId = {{ $lesson->id }}; $(function() { var timeout; $("#player").on("playing pause", function(e) { var v = this clearTimeout(timeout) performaction(v.currentTime, v.duration) if (e.type === "playing") { timeout = setInterval(function() { performaction(v.currentTime, v.duration) }, 3000) // 可以根据需求调整间隔,比如5秒减少请求频率 } }) function performaction(currentTime, duration) { console.log(`当前播放时长: ${currentTime}, 课程ID: ${lessonId}`); // 发送Ajax请求到后端 $.ajax({ url: "{{ route('watch-history.update') }}", // 后端命名路由 method: "POST", data: { lesson_id: lessonId, current_time: Math.round(currentTime), // 取整存储,避免小数精度问题 duration: duration }, headers: { // 带上CSRF令牌,Laravel会验证POST请求的合法性 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, success: function(response) { console.log("观看历史更新成功:", response); }, error: function(xhr) { console.error("更新失败:", xhr.responseText); } }); } }) </script>
二、后端路由配置(routes/web.php)
添加一个带登录验证的POST路由,指向我们即将创建的控制器方法:
use App\Http\Controllers\WatchHistoryController; Route::post('/watch-history/update', [WatchHistoryController::class, 'update']) ->name('watch-history.update') ->middleware('auth'); // 确保只有登录用户才能更新
三、创建并编写控制器
先通过Artisan命令生成控制器:
php artisan make:controller WatchHistoryController
然后在app/Http/Controllers/WatchHistoryController.php里编写update方法,处理前端传过来的数据:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class WatchHistoryController extends Controller { public function update(Request $request) { // 验证请求数据的合法性 $request->validate([ 'lesson_id' => 'required|integer', 'current_time' => 'required|numeric|min:0', 'duration' => 'required|numeric|min:0' ]); // 获取当前登录用户 $user = Auth::user(); // 取出用户的观看历史,为空则初始化空数组 $watchHistory = $user->watch_history ?? []; // 查找是否已存在该课程的观看记录 $lessonIndex = array_search($request->lesson_id, array_column($watchHistory, 'lesson_id')); if ($lessonIndex !== false) { // 存在则更新当前播放时长和总时长 $watchHistory[$lessonIndex]['current_time'] = $request->current_time; $watchHistory[$lessonIndex]['duration'] = $request->duration; } else { // 不存在则添加新记录 $watchHistory[] = [ 'lesson_id' => $request->lesson_id, 'current_time' => $request->current_time, 'duration' => $request->duration ]; } // 更新用户的watch_history字段 $user->update([ 'watch_history' => $watchHistory ]); // 返回成功响应给前端 return response()->json([ 'status' => 'success', 'message' => '观看历史已更新', 'data' => $watchHistory ]); } }
四、数据库字段与模型配置
- 添加watch_history字段
如果你的users表还没有这个字段,生成迁移:
php artisan make:migration add_watch_history_to_users_table
打开迁移文件,设置字段为JSON类型:
public function up() { Schema::table('users', function (Blueprint $table) { $table->json('watch_history')->nullable(); }); } public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('watch_history'); }); }
运行迁移:
php artisan migrate
- User模型配置
在app/Models/User.php里添加字段映射和可填充设置,让Laravel自动把JSON转成数组:
class User extends Authenticatable { // ...其他代码 // 把JSON字段自动转为数组 protected $casts = [ 'email_verified_at' => 'datetime', 'watch_history' => 'array' ]; // 允许批量赋值的字段 protected $fillable = [ 'name', 'email', 'password', 'watch_history' // 新增这个 ]; }
一些优化建议
- 你当前是每3秒发送一次请求,可根据需求调整间隔(比如5秒),或者只在用户暂停播放、播放进度变化超过一定阈值时发送,减少服务器压力;
- 测试时可以查看Laravel日志(
storage/logs/laravel.log)或直接查看数据库,确认数据是否正确存储; - 后续做续看功能时,只需要从用户的
watch_history数组里找到对应lesson_id的current_time,设置给视频播放器即可。
内容的提问来源于stack exchange,提问作者Abhishek pardeshi
相关产品推荐
相关产品推荐

