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

Laravel Eloquent左关联时两个外键指向同主表id的查询方法

解决方案

错误原因说明

你当前的写法存在两个核心问题:

  • 仅对users表做了一次关联,无法同时匹配created_by和approved_by两个不同的外键值
  • 多条件join的写法逻辑错误,相当于要求created_by和approved_by必须等于同一个用户ID,只有创建人和审批人是同一个用户时才能匹配到数据,且两个name字段取值完全相同

方案1:使用Eloquent关联关系(推荐)

这是Laravel框架原生推荐的写法,代码简洁易维护:

  1. 首先在JobPosting模型中定义两个关联方法:
// app/Models/JobPosting.php
public function createdBy()
{
    return $this->belongsTo(User::class, 'created_by');
}

public function approvedBy()
{
    return $this->belongsTo(User::class, 'approved_by');
}

// 你之前关联的其他表也可以统一用关联定义,比如dealership、department、position同理
  1. 查询时使用预加载with方法:
$job_postings = JobPosting::with(['createdBy', 'approvedBy', 'dealership', 'department', 'position'])
    ->where('id', $jp_id)
    ->get();
  1. 数据处理时直接取关联属性即可:
foreach($job_postings as $job_posting){
    $data[] = [
        'job_posting_id'  => $job_posting->job_posting_id, 
        'dealership_name' => $job_posting->dealership?->dealership_name,
        'department_name' => $job_posting->department?->department_name,
        'position_name'   => $job_posting->position?->position_name,
        'qualifications'  => $job_posting->qualifications,
        'status'          => $job_posting->status == 0 ? 'Pending' : 'Approved',
        'created_by'      => $job_posting->createdBy?->name,
        'approved_by'     => $job_posting->approvedBy?->name,
        'created_at'      => $job_posting->created_at->format('D, d M Y | h:i A'),
        'updated_at'      => $job_posting->updated_at->format('D, d M Y | h:i A'),
    ];
}

提示:?->为空安全运算符,避免关联数据不存在时报错,Laravel 8+版本支持


方案2:修改现有JOIN写法

如果你不想改原有代码结构,只需要将users表关联两次,分别设置别名即可:

$job_postings = JobPosting::select(
    'job_postings.id as job_posting_id',
    'job_postings.qualifications',
    'job_postings.created_at',
    'job_postings.updated_at',
    'job_postings.created_by',
    'job_postings.approved_by',
    'dealerships.dealership_name',
    'departments.department_name',
    'positions.position_name',
    'creators.name as created_by_name', // 取创建者别名表的name
    'approvers.name as approved_by_name', // 取审批者别名表的name
    DB::raw("case when job_postings.status = 0 then 'Pending' else 'Approved' end status"),
)
->leftJoin('dealerships', 'job_postings.dealership_id', '=', 'dealerships.id')
->leftJoin('departments', 'job_postings.department_id', '=', 'departments.id')
->leftJoin('positions', 'job_postings.position_id', '=', 'positions.id')
// 第一次关联users表,别名creators,匹配创建人
->leftJoin('users as creators', 'job_postings.created_by', '=', 'creators.id')
// 第二次关联users表,别名approvers,匹配审批人
->leftJoin('users as approvers', 'job_postings.approved_by', '=', 'approvers.id')
->where('job_postings.id', $jp_id)
->get();

修改后你原有foreach处理逻辑无需调整,可直接获取到两个不同的用户姓名。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 01:27:03