Laravel 如何编写子查询实现 Receipts 关联 Ingradients 表返回嵌套结构数据
Laravel 嵌套结构查询实现方案
1. 定义模型关联
首先在对应模型中配置一对多关联关系:
Receipt 模型
// app/Models/Receipt.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Receipt extends Model { // 非默认表名需手动指定 protected $table = 'Receipts'; // 定义和食材表的一对多关联 public function ingradients(): HasMany { // 参数依次为:关联模型、外键名、当前模型主键名 return $this->hasMany(Ingradient::class, 'id_receipt', 'id'); } }
Ingradient 模型
// app/Models/Ingradient.php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Ingradient extends Model { protected $table = 'Ingradients'; // 表无created_at/updated_at字段时需关闭自动时间戳 public $timestamps = false; }
2. 执行关联查询
使用 Laravel 预加载方法with查询即可自动生成嵌套结构:
// 查询所有菜谱及对应食材 $receipts = Receipt::with('ingradients')->get(); // 查询单个id为5的菜谱及对应食材 $receipt = Receipt::with('ingradients')->find(5); // 直接返回即可得到要求的JSON格式 return $receipts;
3. 可选优化:指定查询字段
如果不需要表中全部字段,可通过闭包筛选返回字段,减少数据传输:
$receipts = Receipt::select('id', 'name', 'advice') ->with([ 'ingradients' => function($query) { // 关联查询必须包含外键id_receipt,否则关联无法匹配 $query->select('id_ingradient', 'id_receipt', 'ingradient', 'type_measuring'); } ]) ->get();
注意事项
- 预加载
with方法可避免N+1查询问题,性能远高于循环查询子数据 - 自定义外键必须在关联方法中显式指定,否则Laravel会默认使用
receipt_id作为外键导致关联失败 - 关联子查询中必须包含关联外键
id_receipt,否则无法正确匹配父子数据
内容的提问来源于stack exchange,提问作者Nazariy Tymoschuk
相关产品推荐
相关产品推荐

