Laravel Eloquent模型:如何让查询方法返回关联贡献者数据?
解决方案
完全不需要放弃Eloquent,用Laravel自带的关联模型和自动加载就能实现你的需求,步骤如下:
1. 定义模型关联
首先在Book模型中定义与Author的多对多关联,通过中间表contribution关联,同时指定要获取中间表的role字段:
// app/Models/Book.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Book extends Model { // 定义与作者的多对多关联 public function contributors(): BelongsToMany { return $this->belongsToMany(Author::class, 'contribution', 'book_id', 'contributor_id') ->withPivot('role'); // 取出中间表的role字段 } }
2. 自动加载关联
如果你希望每次查询Book时自动带上贡献者数据,只需在Book模型中添加$with属性,这样all()、find()、get()等方法返回的结果都会自动包含contributors:
// app/Models/Book.php class Book extends Model { // ... 其他代码 protected $with = ['contributors']; // 自动加载关联 }
3. 调整返回格式(可选)
默认情况下,关联返回的contributors会包含pivot对象存储role,如果想让role和id、name同级,可以在Book模型中定义访问器重写contributors属性:
// app/Models/Book.php class Book extends Model { // ... 其他代码 public function getContributorsAttribute() { return $this->contributors->map(function ($author) { return [ 'id' => $author->id, 'name' => $author->name, 'role' => $author->pivot->role ]; }); } }
效果验证
现在执行Book::find(1)->toArray(),返回的结构就和你期望的一致:
[ "id" => "1", "title" => "CS101", "contributors" => [ [ "id" => "1", "name" => "Einstein", "role" => "author" ], [ "id" => "2", "name" => "Thomas", "role" => "translator" ] ] ]
这种方式完全遵循Eloquent的设计理念,不需要重写核心方法,既优雅又易于维护。
内容的提问来源于stack exchange,提问作者Đức Thành Nguyễn
相关产品推荐
相关产品推荐

