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

Laravel使用嵌套with关联truckHistory与trukInvoice报错如何解决

问题原因&修正方案

核心错误点

  • 关联定义位置错误:trukInvoice关联放错了模型。该关联依赖invoice_details表的invoice_id字段,应该定义在InvoiceDetail模型中,而不是Truck模型中。
  • 控制器查询逻辑错误:Truck::find($id)会直接执行SQL返回对应id的模型实例,后续调用with()会重新开启查询构造器,最后的first()会返回trucks表的第一条数据,完全不符合需求。
  • 预加载写法冗余:嵌套预加载无需写闭包,Laravel支持关联.子关联的语法直接加载多级关联。

修正步骤

1. 调整关联定义

将Truck模型中的trukInvoice方法迁移到InvoiceDetail模型中:

// app/Models/InvoiceDetail.php 新增关联
public function trukInvoice()
{
    return $this->belongsTo(Invoice::class, 'invoice_id', 'id');
}

删除Truck模型中原本的trukInvoice方法。

2. 修正控制器查询代码

public function getTruck($id)
{
    // 直接使用嵌套预加载语法加载关联
    $truck = Truck::with('truckHistory.trukInvoice')->find($id);
    return $truck;
}

如果需要给truckHistory加额外查询条件,再使用闭包写法:

public function getTruck($id)
{
    $truck = Truck::with([
        'truckHistory' => function($query) {
            // 此处可加自定义查询条件,例:$query->where('created_at', '>', '2024-01-01');
            $query->with('trukInvoice');
        }
    ])->find($id);
    return $truck;
}

额外优化建议

你当前定义的getCompanyNameAttribute访问器中,$this->companys()->first()->name每次调用都会触发新的SQL查询,存在N+1性能问题。建议修改为:

public function getCompanyNameAttribute()
{
   return optional($this->companys)->name;
}

查询时同步预加载companys关联即可:Truck::with(['companys', 'truckHistory.trukInvoice'])->find($id);

内容的提问来源于stack exchange,提问作者Tuana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:27:00