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

Laravel中获取全层级分类商品及分页展示问题

问题背景

我有一个多层级分类结构:
Parent - child one - child two - child two (one)

当访问Parent页面时,需要获取该分类及其所有子层级(Parent、child one、child two、child two(one))的商品,而不只是父分类下的商品。

当前遇到两个问题:

  1. 怎么才能获取上述所有层级分类下的商品?
  2. 如何在Parent页面实现这些商品的分页展示?

现有代码(仅能展示父分类下的商品):

public function totalcategoriessubs($catslug) { 
    $categories = Category::where('slug','=',$catslug)->with('childs')->paginate(12); 
    $products = Product::whereHas('category', function($q) use($catslug){ 
        $q->where('slug',$catslug); 
    })->paginate(12); 
    return view('front.categoriessubs', compact('products', 'categories')); 
}

我更新后的代码(能拿到Parent、child one、child two层级的商品,但拿不到child two(one)的商品):

public function totalcategoriessubs($catslug) { 
    //changed 
    $category = Category::where('slug','=',$catslug)->with('childs')->first(); 
    //testing this 
    $products = Product::whereHas('category', function($q) use ($catslug,$category) { 
        $q->where(function($q) use ($catslug,$category) { 
            $q->where('slug',$catslug)->orWhere('category_id',$category->id); 
        }); 
    })->orderBy('created_at', 'DESC')->paginate(10); 
    //end testing 
    return view('front.categoriessubs', compact('products', 'category')); 
}

解决方案

1. 先搞定所有层级的分类ID

你现在的问题核心是:当前代码只覆盖了父分类本身和它的直接子分类(比如child one、child two),但像child two(one)这种更深层的子分类,它的category_id是child two的ID,不是Parent的ID,所以没被查询到。

我们需要先把Parent下面所有层级的分类ID都收集起来,包括父分类自己。

首先,确保你的Category模型里已经定义了递归的子分类关系(如果还没加的话):

// app/Models/Category.php
public function childs()
{
    // 关联子分类,并且递归加载子分类的子分类
    return $this->hasMany(Category::class, 'category_id', 'id')->with('childs');
}

然后,在控制器里加一个私有方法,用来递归收集所有分类ID:

// 控制器内的私有方法
private function getAllCategoryIds(Category $category)
{
    // 先把当前分类ID加进去
    $ids = [$category->id];
    
    // 遍历所有子分类,递归收集它们的ID
    foreach ($category->childs as $child) {
        $ids = array_merge($ids, $this->getAllCategoryIds($child));
    }
    
    return $ids;
}

2. 修改商品查询逻辑

现在用上面的方法拿到所有相关分类的ID,然后用whereIn来查询属于这些分类的商品:

public function totalcategoriessubs($catslug) { 
    // 获取父分类,同时递归加载所有子分类
    $category = Category::where('slug','=',$catslug)->with('childs')->first(); 

    // 拿到父分类+所有子分类的ID数组
    $categoryIds = $this->getAllCategoryIds($category);

    // 查询所有属于这些分类的商品,同时做分页
    $products = Product::whereHas('category', function($q) use ($categoryIds) { 
        $q->whereIn('id', $categoryIds); 
    })->orderBy('created_at', 'DESC')->paginate(10); 

    return view('front.categoriessubs', compact('products', 'category')); 
}

3. 分页展示的实现

其实你已经用了paginate(10),这一步Laravel已经帮你处理了分页逻辑。你只需要在前端视图里添加分页链接就行,直接调用分页对象的links()方法:

{{-- 在你的 front/categoriessubs.blade.php 视图文件中 --}}
<div class="pagination-container">
    {{ $products->links() }}
</div>

这个方法会自动生成带页码的分页导航,点击就能切换不同页的商品。

可选优化(针对大量分类的情况)

如果你的分类层级特别深、数量特别多,递归遍历可能会有点性能问题。这时候可以考虑用嵌套集合(Nested Set)来优化,比如用kalnoy/nestedset这个Laravel包,它能更高效地查询所有子分类,不用递归遍历。不过如果你的分类规模不大,上面的递归方法完全够用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:36