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

Laravel 9+Inertia.js多表数据查询优化方案咨询

Laravel 9 + Inertia.js 设备列表查询优化方案

一、解决主关联(company/modele/uklad)的N+1查询问题

你已经在Device模型定义了belongsTo关联,直接用**预加载(Eager Loading)**就能替代闭包里的单独查询:

1. 确认Device模型的关联定义(确保已正确设置)

// app/Models/Device.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Device extends Model
{
    // 关联公司
    public function company()
    {
        return $this->belongsTo(Company::class);
    }

    // 关联型号
    public function modele()
    {
        return $this->belongsTo(Modele::class);
    }

    // 关联系统
    public function uklad()
    {
        return $this->belongsTo(Uklad::class);
    }

    // 关联设备位置中间表
    public function deviceLokale()
    {
        return $this->hasMany(DeviceLokale::class);
    }
}

2. 控制器中添加预加载

在查询Device列表时,用with()方法一次性加载所有需要的关联数据,替代循环内的单独查询:

// 控制器代码示例
use App\Models\Device;
use Inertia\Inertia;

public function index()
{
    // 预加载所有关联,包括嵌套的Lokale
    $devices = Device::with([
        'company', 
        'modele', 
        'uklad',
        'deviceLokale.lokale' // 嵌套预加载:先加载deviceLokale,再加载对应的Lokale
    ])->get();

    // 如果是分页场景,改成paginate即可
    // $devices = Device::with([...])->paginate(15);

    return Inertia::render('Devices/Index', [
        'devices' => $devices
    ]);
}

二、优化DeviceLokale与Lokale的关联查询

通过嵌套预加载deviceLokale.lokale,可以一次性获取所有设备对应的位置数据,无需在前端或闭包中循环查询:

1. 确认关联模型定义

// app/Models/DeviceLokale.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class DeviceLokale extends Model
{
    // 关联位置表
    public function lokale()
    {
        return $this->belongsTo(Lokale::class);
    }
}

2. 前端直接访问关联数据

在Inertia的Vue/React组件中,直接通过预加载后的属性访问关联数据,无需再发起额外请求:

<!-- Vue组件示例 -->
<template>
  <div>
    <table>
      <thead>
        <tr>
          <th>设备名称</th>
          <th>所属公司</th>
          <th>型号</th>
          <th>系统</th>
          <th>所在位置</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="device in devices" :key="device.id">
          <td>{{ device.name }}</td>
          <!-- 直接访问预加载的company关联 -->
          <td>{{ device.company?.name }}</td>
          <td>{{ device.modele?.name }}</td>
          <td>{{ device.uklad?.name }}</td>
          <!-- 遍历预加载的deviceLokale及其关联的lokale -->
          <td>
            <span v-for="dl in device.deviceLokale" :key="dl.id">
              {{ dl.lokale?.name }}
            </span>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

关键原理说明

预加载通过with()方法将原本的N+1次数据库查询(1次查所有设备,N次查每个设备的关联)合并为1 + M次查询(M是关联表的数量),大幅减少数据库请求次数,提升页面加载速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 15:10:16