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

如何基于自身年份条件预加载EmployeeAchievement关联的PositionAllowance

问题

现有以下5个模型:

  • Year
  • Position
  • PositionAllowance:Position与Year的中间表,新增allowance字段,用于定义指定年份下各职位的津贴金额。
  • Employee
  • EmployeeAchievement:记录员工绩效,存储员工当前职位及对应年份信息。

需求:获取EmployeeAchievement记录时,如何根据其自身的年份,预加载对应的唯一PositionAllowance?优先使用Eloquent实现,也接受其他方案。

数据示例

> Year
  >> id: 1 , year: 2023
  >> id: 2 , year: 2024

> Position
  >> id: 1 , name: Junior
  >> id: 2 , name: Senior

> PositionAllowance
  >> id: 1 , position_id: 1 , year_id: 1 , allowance: 100    // 2023年,Junior职位津贴100美元
  >> id: 2 , position_id: 1 , year_id: 2 , allowance: 200    // 2024年,Junior职位津贴200美元

> Employee
  >> id: 1 , name: Joe , position_id: 1

> EmployeeAchievement
  >> id: 1 , employee_id: 1 , current_position_id: 1 , year_id: 1   // 2023年Joe应得100美元津贴
  >> id: 2 , employee_id: 1 , current_position_id: 1 , year_id: 2   // 2024年Joe应得200美元津贴

期望结果

EmployeeAchievement[0] => id: 1
                          employee => id: 1 , name: Joe
                          ....
                          positionAllowance => id: 1 , allowance: 100

EmployeeAchievement[1] => id: 2
                          employee => id: 1 , name: Joe
                          ....
                          positionAllowance => id: 2 , allowance: 200

解决方案

方法一:Eloquent关联实现(推荐)

在EmployeeAchievement模型中定义关联方法,通过自身的current_position_id和year_id匹配对应的PositionAllowance:

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

use Illuminate\Database\Eloquent\Model;

class EmployeeAchievement extends Model
{
    // 关联员工模型
    public function employee()
    {
        return $this->belongsTo(Employee::class);
    }

    // 关联对应年份和职位的津贴
    public function positionAllowance()
    {
        return $this->hasOne(PositionAllowance::class)
            ->whereColumn('position_id', 'current_position_id')
            ->whereColumn('year_id', 'year_id');
    }
}

查询时直接预加载关联关系,就能得到包含对应津贴的结果:

$achievements = EmployeeAchievement::with(['employee', 'positionAllowance'])->get();

方法二:查询构造器手动关联

如果不需要定义模型关联,也可以通过JOIN查询直接整合数据:

$achievements = EmployeeAchievement::select(
        'employee_achievements.*',
        'position_allowances.id as allowance_id',
        'position_allowances.allowance'
    )
    ->leftJoin('position_allowances', function ($join) {
        $join->on('position_allowances.position_id', '=', 'employee_achievements.current_position_id')
             ->on('position_allowances.year_id', '=', 'employee_achievements.year_id');
    })
    ->with('employee')
    ->get();

这种方式会把津贴字段直接附加到EmployeeAchievement实例中,同样能满足需求。

注意事项

  • 确保PositionAllowance表中position_id和year_id的组合是唯一约束,避免出现多条匹配结果导致关联异常。
  • 如果需要处理无对应津贴的场景,使用leftJoin(对应Eloquent的hasOne默认是内联,若要左联可改为hasOne(...)->withDefault())。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 09:47:47