You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 12:03:14