Laravel中为课程关联多视频:迁移、控制器及模型实现方法咨询
实现课程与多视频的关联管理(Ruby on Rails 示例)
这是典型的一对多关联场景,一门课程对应多个视频课时,下面从Model、Migration、Controller三个层面给出具体实现方案:
1. Model 层定义
通过has_many和belongs_to建立课程与视频的关联:
# app/models/course.rb class Course < ApplicationRecord # 删除课程时自动删除关联的视频,避免孤儿数据 has_many :videos, dependent: :destroy end
# app/models/video.rb class Video < ApplicationRecord # 视频必须属于某一门课程 belongs_to :course end
2. Migration 数据库表设计
首先创建课程表,再创建包含外键的视频表:
课程表迁移
执行生成命令:
rails generate migration CreateCourses title:string description:text
生成的迁移文件内容如下(可直接运行rails db:migrate):
# db/migrate/[timestamp]_create_courses.rb class CreateCourses < ActiveRecord::Migration[7.0] def change create_table :courses do |t| t.string :title # 课程标题 t.text :description # 课程描述 t.timestamps end end end
视频表迁移
执行生成命令(自动包含外键关联):
rails generate migration CreateVideos title:string url:string duration:integer position:integer course:references
生成的迁移文件可补充索引优化:
# db/migrate/[timestamp]_create_videos.rb class CreateVideos < ActiveRecord::Migration[7.0] def change create_table :videos do |t| t.string :title # 课时标题 t.string :url # 视频存储路径/第三方播放链接 t.integer :duration # 视频时长(单位:秒) t.integer :position # 课时排序位置,用于控制播放顺序 t.references :course, null: false, foreign_key: true # 关联课程的外键 t.timestamps end # 确保同一课程下的课时位置不重复,同时优化查询性能 add_index :videos, [:course_id, :position], unique: true end end
运行迁移:
rails db:migrate
3. Controller 与路由配置
通过嵌套路由组织课程与视频的关系,让逻辑更清晰:
路由配置
# config/routes.rb Rails.application.routes.draw do resources :courses do # 只保留需要的视频操作动作 resources :videos, only: [:index, :new, :create, :edit, :update, :destroy] end end
视频控制器实现
# app/controllers/videos_controller.rb class VideosController < ApplicationController # 提前加载当前课程 before_action :set_course # 提前加载当前操作的视频 before_action :set_video, only: [:edit, :update, :destroy] # 查看课程下的所有课时(按排序位置升序) def index @videos = @course.videos.order(position: :asc) end # 新建课时页面 def new @video = @course.videos.new end # 创建课时 def create @video = @course.videos.new(video_params) if @video.save redirect_to course_videos_path(@course), notice: '课时添加成功' else render :new end end # 编辑课时页面 def edit end # 更新课时信息 def update if @video.update(video_params) redirect_to course_videos_path(@course), notice: '课时更新成功' else render :edit end end # 删除课时 def destroy @video.destroy redirect_to course_videos_path(@course), notice: '课时删除成功' end private def set_course @course = Course.find(params[:course_id]) end def set_video @video = @course.videos.find(params[:id]) end # 强参数,只允许指定字段提交 def video_params params.require(:video).permit(:title, :url, :duration, :position) end end
额外建议
- 可以给
position字段添加默认值(比如设置为当前课程下视频数量+1),简化排序逻辑 - 如果需要更复杂的课时排序(如拖拽调整),可以使用
acts_as_list这类gem来简化实现 - 视频文件建议存储到云存储服务,数据库只存储文件链接
内容的提问来源于stack exchange,提问作者Morez Dev
相关产品推荐
相关产品推荐

