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

如何通过预加载获取Scheme关联Sponsor的对应ContributionRate数据

问题

我有Scheme和Sponsor两个模型,二者通过中间表SchemeSponsor建立多对多关联。中间表SchemeSponsor与ContributionRate模型是一对多关联。我希望获取某个Scheme关联的所有Sponsor,以及每个Sponsor对应的仅与当前Scheme关联的ContributionRate数据。

各模型字段如下:

  • Scheme:
    • id
    • name
  • Sponsor:
    • id
    • name
  • SchemeSponsor:
    • id
    • sponsor_id
    • scheme_id
    • pivot_data
  • ContributionRate:
    • id
    • scheme_sponsor_id
    • rate

目前我在Sponsor模型中定义了如下关联:

public function contribution_rates()
{
    return $this->hasManyThrough(
        ContributionRates::class,
        SchemeSponsor::class,
        'sponsor_id',
        'scheme_sponsor_id',
        'id',
        'id'
    );
}

但该关联会返回该Sponsor所有的ContributionRate数据,包括和其他Scheme关联的无关数据。我需要通过预加载实现只获取与当前Scheme绑定的中间表对应的ContributionRate数据。

解决方案

1. 调整模型关联,利用中间表模型嵌套关联

hasManyThrough无法直接过滤出绑定特定Scheme的关联数据,我们可以通过多对多关联的中间表模型来嵌套关联ContributionRate:

首先在Scheme模型中正确定义多对多关联,指定中间表模型并带上必要字段:

// Scheme.php
public function sponsors()
{
    return $this->belongsToMany(Sponsor::class)
                ->using(SchemeSponsor::class) // 指定中间表模型
                ->withPivot('id', 'pivot_data'); // 带上中间表ID,用于关联ContributionRate
}

然后在SchemeSponsor模型中定义与ContributionRate的一对多关联:

// SchemeSponsor.php
public function contributionRates()
{
    return $this->hasMany(ContributionRate::class, 'scheme_sponsor_id');
}

2. 嵌套预加载获取目标数据

现在可以通过嵌套预加载,直接从指定Scheme获取关联的Sponsor,以及每个Sponsor对应的绑定当前Scheme的ContributionRate:

$targetSchemeId = 1; // 替换为你的目标Scheme ID
$scheme = Scheme::with('sponsors.pivot.contributionRates')
                ->find($targetSchemeId);

3. 访问数据的方式

获取数据后,可按以下方式访问:

foreach ($scheme->sponsors as $sponsor) {
    // 当前Scheme与该Sponsor的中间表记录
    $schemeSponsor = $sponsor->pivot;
    // 对应的ContributionRate数据
    $rates = $schemeSponsor->contributionRates;
}

替代方案:带条件的动态关联

如果希望直接在Sponsor模型中定义过滤特定Scheme的关联,可以使用闭包传入Scheme ID:

// Sponsor.php
public function contributionRatesForScheme($schemeId)
{
    return $this->hasManyThrough(
        ContributionRate::class,
        SchemeSponsor::class,
        'sponsor_id',
        'scheme_sponsor_id',
        'id',
        'id'
    )->where('scheme_sponsors.scheme_id', $schemeId);
}

预加载时通过闭包指定条件:

$targetSchemeId = 1;
$scheme = Scheme::with(['sponsors' => function ($query) use ($targetSchemeId) {
    $query->with(['contributionRatesForScheme' => function ($q) use ($targetSchemeId) {
        $q->where('scheme_sponsors.scheme_id', $targetSchemeId);
    }]);
}])->find($targetSchemeId);

不过这种方式不如第一种嵌套预加载直观,推荐优先使用第一种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:25:20