Laravel 9中如何为关联表分配Author ID与Paper ID?
Laravel 9 作者-论文多对多关联实现修正方案
一、模型与关联定义
先把模型的多对多关联配置好,Laravel Eloquent自带的关联方法能帮你自动处理中间表,不用手动写DB操作:
1. Papers 模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Papers extends Model { protected $table = 'papers'; protected $primaryKey = 'PaperID'; // 对应你的表主键 public $timestamps = true; // 按你数据库实际情况调整 // 定义与作者的多对多关联 public function authors(): BelongsToMany { // 参数:关联模型、中间表名、当前模型在中间表的外键、关联模型在中间表的外键 return $this->belongsToMany(Authors::class, 'relations', 'paper_ID', 'author_ID'); } }
2. Authors 模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Authors extends Model { protected $table = 'authors'; protected $primaryKey = 'AuthorID'; // 假设你的作者表主键是这个 public $timestamps = true; // 定义与论文的多对多关联 public function papers(): BelongsToMany { return $this->belongsToMany(Papers::class, 'relations', 'author_ID', 'paper_ID'); } }
3. 中间表校验
确保你的relations表有paper_ID和author_ID两个外键字段,分别关联papers.PaperID和authors.AuthorID。
二、修正路由配置
调整路由,确保添加作者时能传递论文ID,并且提交路径对应:
// web.php use App\Http\Controllers\PapersController; use App\Http\Controllers\AuthorsController; Route::resource('papers', PapersController::class); // 新增添加作者的路由,接收论文ID参数 Route::get('papers/{paper}/authors/create', [AuthorsController::class, 'create'])->name('authors.create'); Route::post('papers/{paper}/authors', [AuthorsController::class, 'store'])->name('authors.store');
三、视图代码修正
1. 首页(论文列表)视图
修正循环变量名,链接到正确的添加作者路由:
@extends('layouts.layout') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>论文列表</h2> </div> <div class="pull-right"> <a class="btn btn-success" href="{{ route('papers.create') }}"> 创建新论文</a> </div> </div> </div> @foreach($papers as $paper) <div class="mb-3"> <h4>{{ $paper->title }}</h4> <div class="pull-right"> <a class="btn btn-success" href="{{ route('authors.create', ['paper' => $paper->PaperID]) }}"> 添加作者</a> </div> </div> @endforeach @endsection
2. 添加作者视图
加个隐藏字段传递论文ID,确保提交时能把ID传给控制器:
@extends('layouts.layout') @section('content') <form action="{{ route('authors.store', ['paper' => request()->paper]) }}" method="POST"> @csrf <!-- 隐藏字段传递当前论文ID --> <input type="hidden" name="paper_id" value="{{ request()->paper }}"> <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>名字:</strong> <input type="text" name="Fname" class="form-control" placeholder="First Name"> </div> <div class="form-group"> <strong>姓氏:</strong> <input type="text" name="Lname" class="form-control" placeholder="Last Name"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary">提交</button> </div> </div> </form> @endsection
四、控制器代码修正
1. PapersController 的 index 方法
确保把正确的变量传到视图:
public function index() { $papers = Papers::all(); // 数据多的话可以用分页:Papers::paginate(10) return view('papers.index', compact('papers')); }
2. AuthorsController 的 create 和 store 方法
用Eloquent关联自动处理中间表,不用手动操作Relations模型:
<?php namespace App\Http\Controllers; use App\Models\Authors; use App\Models\Papers; use Illuminate\Http\Request; class AuthorsController extends Controller { public function create($paper) { // 先校验论文是否存在,不存在直接返回404 $paper = Papers::findOrFail($paper); return view('authors.create', compact('paper')); } public function store(Request $request) { // 校验输入合法性 $request->validate([ 'Fname' => 'required|string', 'Lname' => 'required|string', 'paper_id' => 'required|exists:papers,PaperID', ]); // 创建作者 $author = Authors::create([ 'Fname' => $request->Fname, 'Lname' => $request->Lname, ]); // 通过关联绑定作者和论文 $paper = Papers::findOrFail($request->paper_id); $paper->authors()->attach($author->AuthorID); // 直接传$author对象也可以:$paper->authors()->attach($author) return redirect()->route('papers.index')->with('success', '作者添加成功'); } }
五、关联数据展示(可选)
如果要在论文详情页显示作者,按以下步骤做:
1. 新增详情路由
Route::get('papers/{paper}', [PapersController::class, 'show'])->name('papers.show');
2. PapersController 的 show 方法
public function show(Papers $paper) { // 预加载作者,避免N+1查询问题 $paper->load('authors'); return view('papers.show', compact('paper')); }
3. 论文详情视图
@extends('layouts.layout') @section('content') <h2>{{ $paper->title }}</h2> <h3>作者列表:</h3> <ul> @foreach($paper->authors as $author) <li>{{ $author->Fname }} {{ $author->Lname }}</li> @endforeach </ul> <a href="{{ route('papers.index') }}" class="btn btn-primary">返回列表</a> @endsection
关键提示
- Eloquent的
belongsToMany关联会自动处理中间表的增删,attach方法负责添加关联记录,detach负责移除,sync可以同步关联关系。 - 如果你的表主键不是默认的
id,必须在模型里指定$primaryKey,否则关联会出错。 - 加数据验证能避免无效数据入库,比如空名字、不存在的论文ID。
内容的提问来源于stack exchange,提问作者Dynow
相关产品推荐
相关产品推荐

