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

Laravel中如何将DB查询转换为Eloquent关联关系?

重构为Eloquent关联及查询优化方案

首先先修正你原查询里的一个明显问题:rightjoin(table3, table1.id, '=', table3.id) 这里的关联条件应该是 table1.id = table3.table1_id,因为你的table3表外键是table1_id,否则这个关联逻辑不成立,先把这个点纠正。

一、重构为Eloquent关联关系

1. 创建对应模型

先给三个表创建Eloquent模型(默认放在app/Models目录下):

Table1.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Table1 extends Model
{
    protected $table = 'table1';

    // 关联Table2
    public function table2s(): HasMany
    {
        return $this->hasMany(Table2::class, 'table1_id', 'id');
    }

    // 关联Table3
    public function table3s(): HasMany
    {
        return $this->hasMany(Table3::class, 'table1_id', 'id');
    }
}

Table2.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Table2 extends Model
{
    protected $table = 'table2';

    public function table1(): BelongsTo
    {
        return $this->belongsTo(Table1::class, 'table1_id', 'id');
    }
}

Table3.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Table3 extends Model
{
    protected $table = 'table3';

    public function table1(): BelongsTo
    {
        return $this->belongsTo(Table1::class, 'table1_id', 'id');
    }
}

2. 用Eloquent实现原查询逻辑

如果要保持原查询的left join + right join返回结构(合并字段的集合),可以用Eloquent模型来写join:

use App\Models\Table1;

public function something()
{
    $something_var = Table1::leftJoin('table2', 'table1.id', '=', 'table2.table1_id')
        ->rightJoin('table3', 'table1.id', '=', 'table3.table1_id')
        ->select('table1.*', 'table2.column as table2_column', 'table3.column as table3_column')
        ->paginate(10);
}

如果希望返回Table1模型并携带关联的table2和table3数据(而非合并字段),可以用预加载(适合需要操作模型实例的场景):

use App\Models\Table3;

public function something()
{
    // 对应原right join table3的逻辑,先查Table3再关联关联数据
    $something_var = Table3::with(['table1', 'table1.table2s'])
        ->select('table3.*', 'table1.id as table1_id', 'table1.column as table1_column')
        ->paginate(10);
}

二、查询优化方案

  • 明确指定查询字段:永远不要用默认的select *,只查询你需要用到的字段,减少数据传输和内存占用。
  • 添加索引:给table2.table1_id和table3.table1_id添加外键索引,大幅提升join查询效率,执行以下SQL:
    ALTER TABLE table2 ADD INDEX idx_table2_table1_id (table1_id);
    ALTER TABLE table3 ADD INDEX idx_table3_table1_id (table1_id);
    
  • 梳理join逻辑:原查询的left join + right join组合可能导致结果集不符合预期,建议先明确业务需求:如果是要保留所有table3的数据并关联对应table1、table2,用Table3::with()的方式更符合Eloquent设计思想。
  • 分页优化:如果数据量极大,可改用cursorPaginate()替代paginate(),避免查询总条数的开销,适合大数据量分页场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:30:59