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

Laravel 8.12:关联查询无法在子数组中获取Printer title字段

Laravel 8.12:无法在Orders子数组中获取Printer的Title字段

表结构

  • Order表:id, name, printer_id, resource_id
  • Printer表:id, title
  • Resources表:id, name

当前代码

$resources = Resource::with('orders')
->leftJoin('orders', 'resources.id', '=', 'orders.resource_id')  
->leftJoin('printers', 'orders.printer_id', '=', 'printers.id') 
->select('resources.*')
->groupBy('resources.id'); 

当前输出结果

[
  {
    "id": 2,
    "title": "user 2",
    "orders": [
      {
        "id": 190,
        "resource_id": "2",
        "printer_id": 2
      },
      {
        "id": 193,
        "resource_id": "2", 
        "printer_id": 3
      },       
    ]
  },
  {
    "id": 3,
    "title": "user 3",
    "orders": [
      {
        "id": 207,
        "resource_id": "3",
        "printer_id": 3
      }
    ]
  },
  {
    "id": 4,
    "title": "user 4",
    "orders": [
      {
        "id": 466,
        "resource_id": "4",
        "printer_id": 4
      },
      {
        "id": 370,
        "resource_id": "4",
        "printer_id": 5
      }
    ]
  }
]

期望输出结果

[
  {
    "id": 2,
    "orders": [
      {
        "id": 190,
        "resource_id": "2",
        "title": "user 2",
        "printer_id": 2
      },
      {
        "id": 193,
        "resource_id": "2", 
        "title": "user 3",
        "printer_id": 3
      }
    ]
  },
  {
    "id": 3,
    "orders": [
      {
        "id": 207,
        "title": "user 3",
        "resource_id": "3",
        "printer_id": 3
      }
    ]
  },
  {
    "id": 4,
    "orders": [
      {
        "id": 466,
        "title": "user 4",
        "resource_id": "4",
        "printer_id": 4
      },
      {
        "id": 370,
        "title": "user 5",
        "resource_id": "4",
        "printer_id": 5
      }
    ]
  }
]

解决方案

问题根源

  1. 混用了Eloquent关联预加载(with('orders'))和手动join,预加载的orders未关联printer数据;
  2. select('resources.*')仅查询了Resources表字段,未包含Printer的title;
  3. 手动join+groupBy的方式破坏了Eloquent关联逻辑,容易丢失关联数据。

正确实现方式

步骤1:完善模型关联

在Order模型中添加与Printer的关联:

// app/Models/Order.php
public function printer()
{
    return $this->belongsTo(Printer::class);
}

在Resource模型中确保与Order的关联正确:

// app/Models/Resource.php
public function orders()
{
    return $this->hasMany(Order::class);
}

步骤2:嵌套预加载关联数据

直接使用Eloquent嵌套预加载,无需手动join,代码更简洁且符合框架规范:

$resources = Resource::with('orders.printer')->get();

步骤3:调整输出格式(匹配期望结果)

如果需要将Printer的title直接放在orders数组同级,可通过with的闭包自定义查询字段:

$resources = Resource::with(['orders' => function ($query) {
    $query->select('orders.*', 'printers.title')
          ->leftJoin('printers', 'orders.printer_id', '=', 'printers.id');
}])->get();

为什么不推荐手动join?

手动join会将多表数据扁平化,当一个Resource对应多个Order时,会产生重复的Resource记录,必须用groupBy去重,既增加查询复杂度,又容易丢失关联数据。而Eloquent预加载机制会自动处理一对多关联,避免数据重复,同时保持结构清晰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:57:17