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

Laravel如何通过类似hasManyThrough的方式从Account直接获取关联分类及其子分类

代码笔误修正

你给出的模型代码存在两处需要修正的问题,否则关联会无法正常运行:

  1. Post模型的positions()方法当前关联的是Category::class,但你定义的分类模型类名为Position,需要统一类名
  2. Position模型的post()方法里Post ::class多了空格,需修改为Post::class
  3. 中间表post_categories的外键默认按命名规则应为post_id和position_id,如果实际命名不同需要对应调整后续代码的字段名

方案1:直接定义调用方法(最常用)

在Account模型中新增如下方法,即可直接获取该账号下所有Post使用过的分类及其所有子分类:

public function getAllUsedPositionsWithChildren()
{
    // 先查询该账号所有Post关联的分类ID,去重
    $usedPositionIds = $this->posts()
        ->join('post_categories', 'posts.id', '=', 'post_categories.post_id')
        ->distinct()
        ->pluck('post_categories.position_id');

    // 利用嵌套集扩展的查询方法,获取上述分类及所有子分类,结果自动去重
    return Position::whereIn('id', $usedPositionIds)
        ->orWhere(function ($query) use ($usedPositionIds) {
            foreach ($usedPositionIds as $positionId) {
                $query->orWhereDescendantOf($positionId);
            }
        })
        ->get()
        ->unique('id');
}

调用方式:

// 拿到账号实例后直接调用即可
$positions = $account->getAllUsedPositionsWithChildren();
// 如果需要整理为树形结构,调用toTree()方法即可
$positionTree = $positions->toTree();

方案2:定义类hasManyThrough关联(支持预加载)

如果你需要支持关联预加载,可先在Account模型中定义直接关联的分类关联:

public function positions()
{
    return $this->hasManyThrough(
        Position::class,
        Post::class,
        'account_id', // Post表关联Account的外键
        'id', // Position表主键
        'id', // Account表主键
        'id' // Post表主键
    )->join('post_categories', 'posts.id', '=', 'post_categories.post_id')
     ->whereColumn('post_categories.position_id', 'positions.id')
     ->distinct();
}

需要加载子分类时,用预加载嵌套集自带的descendants关联即可:

// 预加载账号的所有关联分类及对应子分类
$account = Account::with(['positions.descendants'])->find($accountId);

性能优化建议

  • 给中间表post_categories的post_id和position_id字段添加联合索引
  • 如果分类数据量极大,可先查询所有用到的分类根节点,再一次性加载所有后代节点减少查询次数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:27:02