基于Laravel的在线考试系统数据库表结构实现求助
Laravel 在线考试系统表结构实现方案
一、适配Laravel的表结构优化(兼容你原有设计逻辑)
你原有设计的整体逻辑是可行的,只需要做两处小调整就能适配Laravel的Eloquent关联规则,避免后续数据维护出错:
- 修正answers表的
qeustion_number拼写错误为question_number - 新增
question_id外键关联questions表的id,避免题号修改后答案和题目匹配错乱
迁移文件编写示例
首先执行命令创建迁移:
# 创建试卷表 php artisan make:migration create_quizzes_table # 创建题目表 php artisan make:migration create_questions_table # 创建答案选项表 php artisan make:migration create_answers_table
试卷表(quizzes,对应你原有的quiz_info)
public function up() { Schema::create('quizzes', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('owner_id')->comment('创建用户ID,关联users表id'); $table->string('quiz_name')->comment('试卷名称'); $table->unsignedTinyInteger('question_qnty')->default(0)->comment('题目数量'); $table->timestamps(); // 外键约束 $table->foreign('owner_id')->references('id')->on('users')->onDelete('cascade'); }); }
题目表(questions)
public function up() { Schema::create('questions', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('quiz_id')->comment('所属试卷ID'); $table->unsignedTinyInteger('question_number')->comment('题目序号'); $table->text('question')->comment('题干内容'); $table->timestamps(); // 约束:同一个试卷下序号不重复,单卷最多12题所以用tinyint足够 $table->unique(['quiz_id', 'question_number']); $table->foreign('quiz_id')->references('id')->on('quizzes')->onDelete('cascade'); }); }
答案选项表(answers)
public function up() { Schema::create('answers', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('quiz_id')->comment('所属试卷ID'); $table->unsignedBigInteger('question_id')->comment('所属题目ID'); $table->unsignedTinyInteger('question_number')->comment('所属题目序号'); $table->string('answer')->comment('选项内容'); $table->boolean('is_right')->default(0)->comment('是否为正确答案:0否1是'); $table->timestamps(); // 约束:同一道题下选项不重复,单题最多4个选项 $table->unique(['question_id', 'id']); $table->foreign('quiz_id')->references('id')->on('quizzes')->onDelete('cascade'); $table->foreign('question_id')->references('id')->on('questions')->onDelete('cascade'); }); }
二、业务限制实现(最多12题/每题最多4个选项)
直接在模型层加事件校验,从底层限制数据新增,避免前端绕过验证:
试卷题目数量限制
在Quiz模型中添加saving事件:
protected static function booted() { static::saving(function ($quiz) { if ($quiz->question_qnty > 12) { throw new \Exception('单张试卷最多设置12道考题'); } }); // 新增题目时自动更新题目数量 static::created(function ($quiz) { $quiz->update(['question_qnty' => $quiz->questions()->count()]); }); }
单题选项数量限制
在Answer模型中添加creating事件:
protected static function booted() { static::creating(function ($answer) { $count = Answer::where('question_id', $answer->question_id)->count(); if ($count >= 4) { throw new \Exception('单道考题最多设置4个选项'); } }); }
三、模型关联配置(方便后续查询操作)
配置完成后可以快速关联查询试卷、题目、选项数据:
Quiz模型
public function questions() { // 按题号排序返回 return $this->hasMany(Question::class)->orderBy('question_number'); }
Question模型
public function quiz() { return $this->belongsTo(Quiz::class); } public function answers() { return $this->hasMany(Answer::class); }
Answer模型
public function question() { return $this->belongsTo(Question::class); }
查询整张试卷的完整数据只需一行代码:
$quiz = Quiz::with('questions.answers')->find($quizId);
如果不想调整原有表结构,直接按你原来的字段编写迁移即可,业务限制和关联逻辑稍作调整就能正常使用。
内容的提问来源于stack exchange,提问作者k_fc_
相关产品推荐
相关产品推荐

