如何构建表单实现Event与Question多对多关联数据录入?
实现Event与Question多对多关联的着陆页及事件管理功能
需求概述
开发着陆页展示events表中的各类事件;点击事件后显示详情及关联questions表的问题表单;同时需要创建支持关联问题的事件创建表单,确保多对多关系数据正确关联与展示。
1. 模型关联定义
根据你的表结构,在模型中明确多对多关联关系:
Event 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Event extends Model { protected $fillable = ['title', 'description', 'date']; // 按实际表字段补充 // 与Question的多对多关联 public function questions(): BelongsToMany { return $this->belongsToMany(Question::class, 'event_question', 'event_id', 'question_id'); } }
Question 模型
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Question extends Model { protected $fillable = ['text', 'type']; // 按实际表字段补充 // 与Event的多对多关联 public function events(): BelongsToMany { return $this->belongsToMany(Event::class, 'event_question', 'question_id', 'event_id'); } }
2. 数据库表结构
events表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(主键) | 事件唯一ID |
| title | varchar | 事件标题 |
| description | text | 事件描述 |
| date | date | 事件日期 |
| created_at | timestamp | 创建时间 |
| updated_at | timestamp | 更新时间 |
questions表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int(主键) | 问题唯一ID |
| text | text | 问题内容 |
| type | varchar | 问题类型(如单选/文本) |
| created_at | timestamp | 创建时间 |
| updated_at | timestamp | 更新时间 |
event_question中间表
| 字段名 | 类型 | 说明 |
|---|---|---|
| event_id | int | 关联事件ID |
| question_id | int | 关联问题ID |
3. 控制器逻辑实现
完善控制器的事件列表、详情展示、事件创建与保存功能:
namespace App\Http\Controllers; use App\Models\Event; use App\Models\Question; use Illuminate\Http\Request; class EventController extends Controller { // 着陆页:按日期展示所有事件 public function index() { $events = Event::orderBy('date', 'asc')->get(); return view('events.index', compact('events')); } // 事件详情页:加载关联问题 public function show(Event $event) { // 预加载关联问题,避免N+1查询 $event->load('questions'); return view('events.show', compact('event')); } // 展示事件创建表单 public function create() { $questions = Question::all(); return view('events.create', compact('questions')); } // 保存事件及关联问题 public function store(Request $request) { // 验证表单数据 $validated = $request->validate([ 'title' => 'required|string|max:255', 'description' => 'nullable|text', 'date' => 'required|date', 'question_ids' => 'nullable|array', 'question_ids.*' => 'exists:questions,id' ]); // 创建事件 $event = Event::create($validated); // 关联选中的问题 if ($request->has('question_ids')) { $event->questions()->attach($request->question_ids); } return redirect()->route('events.index')->with('success', '事件创建成功'); } }
4. 视图实现
着陆页视图(resources/views/events/index.blade.php)
<h1>活动列表</h1> <div class="events-container"> @foreach($events as $event) <div class="event-card"> <h3>{{ $event->title }}</h3> <p>{{ $event->description }}</p> <p>举办日期:{{ $event->date->format('Y-m-d') }}</p> <a href="{{ route('events.show', $event) }}" class="btn">查看详情</a> </div> @endforeach </div> <a href="{{ route('events.create') }}" class="btn btn-primary">创建新活动</a>
事件创建表单视图(resources/views/events/create.blade.php)
<h1>创建新活动</h1> <form method="POST" action="{{ route('events.store') }}"> @csrf <div class="form-group"> <label for="title">活动标题</label> <input type="text" id="title" name="title" value="{{ old('title') }}" required> @error('title') <span class="text-red-500">{{ $message }}</span> @enderror </div> <div class="form-group"> <label for="description">活动描述</label> <textarea id="description" name="description">{{ old('description') }}</textarea> </div> <div class="form-group"> <label for="date">举办日期</label> <input type="date" id="date" name="date" value="{{ old('date') }}" required> @error('date') <span class="text-red-500">{{ $message }}</span> @enderror </div> <div class="form-group"> <label>关联问题</label> @foreach($questions as $question) <div class="checkbox-item"> <input type="checkbox" id="question-{{ $question->id }}" name="question_ids[]" value="{{ $question->id }}" {{ in_array($question->id, old('question_ids', [])) ? 'checked' : '' }}> <label for="question-{{ $question->id }}">{{ $question->text }}</label> </div> @endforeach </div> <button type="submit" class="btn btn-primary">创建活动</button> </form>
事件详情页视图(resources/views/events/show.blade.php)
<h1>{{ $event->title }}</h1> <p>{{ $event->description }}</p> <p>举办日期:{{ $event->date->format('Y-m-d') }}</p> <h2>活动问卷</h2> <form method="POST" action="{{ route('responses.store') }}"> <!-- 可根据需求调整提交路由 --> @csrf <input type="hidden" name="event_id" value="{{ $event->id }}"> @foreach($event->questions as $question) <div class="question-group"> <p>{{ $question->text }}</p> <!-- 根据问题类型渲染对应输入组件,示例为文本框 --> <input type="text" name="responses[{{ $question->id }}]" placeholder="请输入回答"> </div> @endforeach <button type="submit" class="btn btn-primary">提交问卷</button> </form> <a href="{{ route('events.index') }}" class="btn">返回活动列表</a>
5. 路由配置
在routes/web.php中添加路由:
use App\Http\Controllers\EventController; Route::get('/events', [EventController::class, 'index'])->name('events.index'); Route::get('/events/{event}', [EventController::class, 'show'])->name('events.show'); Route::get('/events/create', [EventController::class, 'create'])->name('events.create'); Route::post('/events', [EventController::class, 'store'])->name('events.store');
内容的提问来源于stack exchange,提问作者melissa maria pleitez ramirez
相关产品推荐
相关产品推荐

