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

Laravel Eloquent中如何限定嵌套with查询的结果范围

解决嵌套预加载时过滤当前Fund的Participation问题

问题描述

我需要实现以下循环逻辑,遍历用户的基金、每个基金下的标签,以及该基金下对应标签的参与记录:

foreach($user->funds as $fund)
{
    dump($fund->name);

    foreach($fund->tags as $tag)
    {
        dump('Tag: '.$tag->name);

        foreach($tag->participations as $participation)
        {
            // 当前拿到的是该标签下所有基金的参与记录,我需要的是当前循环的fund下、该标签对应的参与记录
            dump('Participation: '.$participation->id.' User: '.$participation->user_id.' Fund: '.$participation->fund_id);         
        }
    }
}

当前查询语句中,我尝试给participations的查询添加fund_id过滤,但无法直接填入当前循环的fund_id;如果去掉这个where子句,遍历标签时会拿到所有基金的相关参与数据:

$user = User::where('id', $user_id)
    ->with(['funds' => function($query) use ($user_id) {
        $query->with(['tags' => function($query) use ($user_id) {
                $query->where('participations.user_id', $user_id)
                    ->with(['participations' => function($query) use ($user_id) {
                        $query->where('user_id', $user_id)
                            ->where('fund_id', ?); // 无法直接获取当前fund的id
                    }]);
            }]);
    }])
    ->first();

模型结构:

  • User:id
  • Fund:id
  • Tag:id
  • Participation:id、fund_id、user_id、tag_id

解决方案

嵌套预加载是批量查询关联数据,无法直接获取单个fund的id,可通过whereColumn关联participations.fund_id与外层funds.id,确保每个标签只加载对应基金的参与记录:

$user = User::where('id', $user_id)
    ->with(['funds' => function($query) use ($user_id) {
        $query->with(['tags' => function($query) use ($user_id) {
            // 提前过滤出有当前用户参与记录的标签
            $query->whereHas('participations', function($subQuery) use ($user_id) {
                $subQuery->where('user_id', $user_id);
            })
            // 预加载参与记录,同时限制为当前基金下的数据
            ->with(['participations' => function($subQuery) use ($user_id) {
                $subQuery->where('user_id', $user_id)
                         ->whereColumn('participations.fund_id', 'funds.id');
            }]);
        }]);
    }])
    ->first();

原理说明

  • whereColumn('participations.fund_id', 'funds.id')让Laravel在查询参与记录时,自动关联外层funds表的id字段,确保只加载属于当前基金的参与记录。
  • whereHas用于过滤掉无当前用户参与记录的标签,减少不必要的数据加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:15:42