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

Laravel 9嵌套hasManyThrough关系使用withCount报错问题排查

Laravel 9中hasManyThrough关联的嵌套关联统计问题

我在Laravel 9里用hasManyThrough关联了PingtreeGroup到Pingtree(通过PingtreeEntry),现在想统计关联的pingtrees下的tiers总数,用with('pingtrees.tiers')没问题,但加了withCount('pingtrees.tiers')就报错:

Call to undefined method App\Models\PingtreeGroup::pingtrees.tiers()

相关代码:
查询代码:

$pingtreeGroup = PingtreeGroup::where('company_id', $company_id)
                                ->where('id', $id)
                                ->with('pingtrees.tiers')
                                ->withCount('pingtrees.tiers')
                                ->first();

PingtreeGroup的关联:

/**
 * Get the pingtrees for the model
 */
public function pingtrees()
{
    return $this->hasManyThrough(
        Pingtree::class,
        PingtreeEntry::class,
        'pingtree_group_id',
        'id',
        'id',
        'pingtree_id'
    );
}

问题原因

Laravel的withCount不支持直接用关联.子关联这种点语法统计嵌套关联的数量,它要求参数必须是当前模型上直接定义的关联方法名,而非嵌套的关联路径。

解决方案1:在withCount中用闭包统计子关联

统计所有关联pingtree的tiers总数

$pingtreeGroup = PingtreeGroup::where('company_id', $company_id)
                                ->where('id', $id)
                                ->with('pingtrees.tiers')
                                ->withCount([
                                    'pingtrees' => function ($query) {
                                        $query->select(DB::raw('count(tiers.id)'))
                                              ->join('tiers', 'tiers.pingtree_id', '=', 'pingtrees.id');
                                    }
                                ])
                                ->first();

之后可通过$pingtreeGroup->pingtrees_count获取总数。

给每个pingtree单独统计tiers数量

$pingtreeGroup = PingtreeGroup::where('company_id', $company_id)
                                ->where('id', $id)
                                ->with(['pingtrees' => function ($query) {
                                    $query->withCount('tiers');
                                }])
                                ->first();

每个$pingtreeGroup->pingtrees中的模型都会带有tiers_count属性。

解决方案2:定义直接关联到Tiers的hasManyThrough关联

在PingtreeGroup模型中新增直接关联Tier的方法:

/**
 * Get all tiers related to the pingtree group
 */
public function pingtreeTiers()
{
    return $this->hasManyThrough(
        Tier::class,
        PingtreeEntry::class,
        'pingtree_group_id', // PingtreeEntry的外键
        'pingtree_id',       // Tier的外键
        'id',                // PingtreeGroup的主键
        'pingtree_id'        // PingtreeEntry关联Pingtree的外键
    );
}

然后直接使用withCount:

$pingtreeGroup = PingtreeGroup::where('company_id', $company_id)
                                ->where('id', $id)
                                ->with('pingtrees.tiers')
                                ->withCount('pingtreeTiers')
                                ->first();

之后可通过$pingtreeGroup->pingtree_tiers_count获取总数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:55:24