You need to enable JavaScript to run this app. Laravel Eloquent使用with预加载roles关联返回null的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent使用with预加载roles关联返回null的问题排查

Eloquent关联预加载异常问题说明

涉及的关联模型定义

项目中用到Person和Role两个模型,各自定义的多对多关联如下:

  • Person模型中roles关联的实现:
public function roles()
{
    return $this->belongsToMany(Role::class, 'person_role', 'user_id', 'role_id')
        ->where('person_role.org_id', $this->defaultOrgID);
}
  • Role模型中people关联的实现:
public function people()
{
    return $this->belongsToMany(Person::class, 'person_role','role_id', 'user_id');
}

异常表现

  • 单独通过Tinker获取单条Person记录、访问$p->roles属性时,关联数据加载逻辑完全符合预期,能正确按所属组织过滤出对应角色
  • 执行以下带关联预加载的批量查询时,本该返回关联数据的场景下,最终结果里的roles关联值始终为null:
$persons = Person::with('roles')
    //->selectRaw('person.personID, person.lastName, person.firstName, person.login, op.OrgStat1, person.defaultOrgID')
    ->select('person.personID', 'person.lastName', 'person.firstName', 'person.login', 'op.OrgStat1', 'person.defaultOrgID')
    ->leftJoin('person-email as pe', 'pe.personID', '=', 'person.personID')
    ->leftJoin('org-person as op', 'op.personID', '=',
        DB::raw('person.personID and op.orgID = ' . $this->currentPerson->defaultOrgID))
    ->leftJoin('role_user as ru', 'ru.user_id', '=',
        DB::raw('person.personID AND ru.orgID = ' . $this->currentPerson->defaultOrgID .
        ' AND EXISTS (select roles.name from roles where roles.id = ru.role_id and roles.name = "%' . $query . '%")'))
    ->orWhere(function ($q) use ($query) {
        $q->orWhere('person.firstName', 'LIKE', "%$query%")
            ->orWhere('person.lastName', 'LIKE', "%$query%")
            ->orWhere('person.login', 'LIKE', "%$query%")
            ->orWhere('person.personID', 'LIKE', "%$query%")
            ->orWhere('pe.emailADDR', 'LIKE', "%$query%")
            ->orWhere('op.OrgStat1', 'LIKE', "%$query%");
    })->distinct()->get();

排查初期曾怀疑问题和select字段配置有关,但没找到对应的官方文档说明,也无法定位具体触发原因。

核心异常线索

通过dd(DB::getQueryLog())查看数据库执行日志时发现,with('roles')预加载生成的关联查询中,关联定义里本该带上的person_role.org_id过滤条件取值始终为null:

日志记录的实际关联查询语句:

select `roles`.*, `person_role`.`user_id` as `pivot_user_id`, `person_role`.`role_id` as `pivot_role_id` 
from `roles` 
inner join `person_role` on `roles`.`id` = `person_role`.`role_id` 
where `person_role`.`org_id` is null and `person_role`.`user_id` in (1)

已经验证过,Person模型关联定义中引用的$this->defaultOrgID本身是非空值,但预加载执行时始终无法正确读取这个属性值,也不清楚要怎么正确为关联传递这个过滤参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 18:06:04