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

Laravel 10多态关联查询返回null但父模型存在的解决方法

问题分析与解决方案

你的核心问题在于:withWhereHas 仅当闭包内存在实际查询条件时,才会自动过滤掉无 modelable 关联的记录。如果请求中的 firstName/lastName/email/phone 参数全为空,闭包不会添加任何约束,此时 withWhereHas 等价于普通的 with('modelable'),不会排除关联为空的 Application 记录。

解决步骤

要强制排除 modelable 为 null 的记录,你需要:

  1. 无论是否有筛选参数,都添加 has('modelable') 约束,确保仅保留存在关联的 Application;
  2. 优化查询逻辑,避免 orWhereNull 破坏其他条件的逻辑关系;
  3. 根据是否有筛选参数,选择高效的关联加载方式。

修改后的完整代码

// 先判断是否存在modelable相关的筛选条件
$hasModelableFilters = $request->filled(['firstName', 'lastName', 'email', 'phone']);

$applications = Application::query()
    ->where('submitted_at', '>=', Carbon::parse($request->input('from')))
    ->where('submitted_at', '<=', Carbon::parse($request->input('to')))
    // 用闭包包住company_id的条件,避免orWhereNull干扰其他查询逻辑
    ->where(function ($query) use ($company) {
        $query->where('company_id', $company->id);
        if ($company->is_default) {
            $query->orWhereNull('company_id');
        }
    })
    ->when($request->input('affiliates'), function ($query, $affiliates) {
        $query->whereIn('affiliate_id', $affiliates);
    })
    ->when($request->input('campaigns'), function ($query, $campaigns) {
        $query->whereIn('campaign_id', $campaigns);
    })
    ->with(['redirect', 'campaign', 'affiliate'])
    // 强制筛选存在modelable关联的记录
    ->has('modelable')
    // 根据是否有筛选条件选择关联加载方式
    ->when($hasModelableFilters, function ($query) use ($request) {
        $query->withWhereHas('modelable', function ($query) use ($request) {
            if ($request->input('firstName')) {
                $query->where('AppFirstName', $request->input('firstName'));
            }
            if ($request->input('lastName')) {
                $query->where('AppLastName', $request->input('lastName'));
            }
            if ($request->input('email')) {
                $query->where('AppEmail', $request->input('email'));
            }
            if ($request->input('phone')) {
                $query->where('AppMobilePhone', $request->input('phone'));
            }
        });
    }, function ($query) {
        // 无筛选条件时直接加载关联,避免不必要的子查询
        $query->with('modelable');
    })
    ->orderBy('submitted_at', 'desc')
    ->paginate($request->input('perPage', 10))
    ->onEachSide(1);

if ($applications->isEmpty()) {
    return new ApiSuccessResponse(null, [
        'message' => 'No applications found.',
    ], 404);
}

关键说明

  • has('modelable'):直接筛选出存在 modelable 关联的记录,从根源上排除关联为空的数据;
  • 用闭包包住 company_id 条件:避免 orWhereNull 与其他 where 条件产生逻辑冲突,保证查询逻辑的正确性;
  • when 方法的使用:根据是否有筛选参数动态选择关联加载方式,提升查询效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:57:23