You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Laravel的在线考试系统数据库表结构实现求助

Laravel 在线考试系统表结构实现方案

一、适配Laravel的表结构优化(兼容你原有设计逻辑)

你原有设计的整体逻辑是可行的,只需要做两处小调整就能适配Laravel的Eloquent关联规则,避免后续数据维护出错:

  1. 修正answers表的qeustion_number拼写错误为question_number
  2. 新增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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:18:04