如何用Laravel Eloquent关联查询获取指定嵌套关联数据?
问题描述
现有transaction表与debt_payment表,Transaction模型已定义与DebtPayment的hasMany关联(debtPayment方法)。需要获取ID为8的交易数据,同时加载其关联的debt_payment记录,且每条debt_payment需包含parent_id对应的关联交易信息。当前编写的Eloquent查询无法得到预期结果,求正确写法。
表结构
transaction表
id invoice_no 3 arm0003 4 arm0004 8 arm0008
debt_payment表
id transaction_id parent_id 1 8 3 2 8 4
现有模型代码
Transaction模型
public function debtPayment() { return $this->hasMany(DebtPayment::class, 'transaction_id'); }
预期输出
Transaction_data_array: [▼ "id" => 8 "invoice_no" => 'arm0008' "debt_payment" => array:1 [▼ 0 => array:4 [▼ "id" => 1 "transaction_id" => 8 "parent_id" => 3 "transaction" => array:2 [▼ "id" => 3 "invoice_no" => 'arm0003' ] ], 1 => array:4 [▼ "id" => 2 "transaction_id" => 8 "parent_id" => 4 "transaction" => array:2 [▼ "id" => 4 "invoice_no" => 'arm0004' ] ] ] ]
当前错误查询代码
$id = 8; $transaction = Transaction::where('id',$id) ->with('debtPayment') ->whereHas('debtPayment', function ($query) use($id){ $query->select('*') ->from('transactions') ->whereIn('id', function($query) use($id){ $query->select('parent_id') ->from('debt_payments') ->where('transaction_id', $id) ->pluck('parent_id'); }) ->get(); }) ->first();
正确解决方案
1. 给DebtPayment模型添加关联方法
首先在DebtPayment模型中定义与Transaction的关联,对应parent_id字段:
// app/Models/DebtPayment.php public function transaction() { return $this->belongsTo(Transaction::class, 'parent_id'); }
(方法名设为transaction是为了匹配预期输出中的键名,也可根据需求自定义为parentTransaction等)
2. 使用嵌套预加载编写查询
利用Eloquent的嵌套预加载功能,一次性加载主交易、关联的debt_payment,以及每个debt_payment对应的父交易:
$id = 8; $transaction = Transaction::where('id', $id) ->with('debtPayment.transaction') // 嵌套预加载关联层级 ->first();
说明
原错误代码误用了whereHas——whereHas的作用是过滤主模型数据,而非加载关联的关联数据。通过嵌套预加载with('debtPayment.transaction'),Eloquent会先查询ID为8的主交易,再查询其关联的所有debt_payment记录,最后批量查询这些debt_payment中parent_id对应的交易数据,既避免了N+1查询问题,又能得到预期的层级结构数据。
内容的提问来源于stack exchange,提问作者golden goal
相关产品推荐
相关产品推荐

