Laravel Eloquent左关联时两个外键指向同主表id的查询方法
解决方案
错误原因说明
你当前的写法存在两个核心问题:
- 仅对
users表做了一次关联,无法同时匹配created_by和approved_by两个不同的外键值 - 多条件join的写法逻辑错误,相当于要求
created_by和approved_by必须等于同一个用户ID,只有创建人和审批人是同一个用户时才能匹配到数据,且两个name字段取值完全相同
方案1:使用Eloquent关联关系(推荐)
这是Laravel框架原生推荐的写法,代码简洁易维护:
- 首先在
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同理
- 查询时使用预加载
with方法:
$job_postings = JobPosting::with(['createdBy', 'approvedBy', 'dealership', 'department', 'position']) ->where('id', $jp_id) ->get();
- 数据处理时直接取关联属性即可:
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
相关产品推荐
相关产品推荐

