You need to enable JavaScript to run this app. Laravel中实现无限级分类按层级递归排序及分页的方法
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中实现无限级分类按层级递归排序及分页的方法

Laravel 无限层级分类递归展示与分页实现方案

前置准备:表结构设计

首先确保你的分类表包含基础层级字段,推荐字段如下:

  • id:主键
  • name:分类名称
  • parent_id:父分类ID,顶级分类默认值为0或NULL
  • sort:同层级排序字段(可选,用于自定义同层级分类的展示顺序)

小数据量实现方案(分类数<100)

如果分类总量不大,可以先递归把所有分类整理为带层级的扁平化集合,再手动生成分页器。

1. 模型添加递归拉平方法

在app/Models/Category.php中添加获取扁平化分类的方法:

public static function getFlattenedTree(int $parentId = 0, int $depth = 0): \Illuminate\Support\Collection
{
    $result = collect();
    // 按排序规则查询当前层级分类
    $categories = self::where('parent_id', $parentId)
        ->orderBy('sort', 'asc')
        ->orderBy('id', 'asc')
        ->get();
    foreach ($categories as $category) {
        // 给当前分类附加层级深度字段,用于前端缩进展示
        $category->depth = $depth;
        $result->push($category);
        // 递归合并子分类
        $result = $result->merge(self::getFlattenedTree($category->id, $depth + 1));
    }
    return $result;
}

2. 控制器手动生成分页器

Laravel默认分页只支持查询构造器,因此需要手动对集合做分页处理:

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;

public function index(Request $request)
{
    // 获取全部整理好的扁平化分类
    $allCategories = Category::getFlattenedTree();
    $perPage = 10;
    $currentPage = Paginator::resolveCurrentPage('page');
    // 切割当前页需要的10条数据
    $pageItems = $allCategories->slice(($currentPage - 1) * $perPage, $perPage)->values();
    // 生成长度感知分页器
    $categories = new LengthAwarePaginator(
        $pageItems,
        $allCategories->count(),
        $perPage,
        $currentPage,
        ['path' => Paginator::resolveCurrentPath()]
    );
    return view('categories.index', compact('categories'));
}

3. 前端渲染加缩进

在Blade模板中根据depth字段控制缩进,实现层级展示效果:

<ul>
    @foreach($categories as $category)
        <li style="padding-left: {{ $category->depth * 20 }}px">
            {{ $category->name }}
        </li>
    @endforeach
</ul>
<!-- 输出分页链接 -->
{{ $categories->links() }}

大数据量优化方案(分类数≥100,推荐)

如果分类总量很大,递归拉全量数据会有性能问题,推荐使用**嵌套集合(Nested Set)**模型实现:

  1. 安装kalnoy/nestedset扩展,按照文档配置Category模型,扩展会自动维护lft、rgt、depth三个字段,用于标识分类的层级和顺序
  2. 查询时直接按lft字段升序排序,即可得到父分类在前、子分类紧跟的递归顺序,直接调用Laravel自带的分页方法即可:
$categories = Category::orderBy('lft', 'asc')->paginate(10);

前端渲染逻辑和小数据量方案完全一致,无需额外处理。

注意事项

  • 若需要自定义同层级分类的排序规则,可以在排序条件中额外增加sort字段,比如orderBy('sort', 'asc')->orderBy('lft', 'asc')
  • 使用嵌套集合模型时,新增、修改、移动、删除分类都要使用扩展包提供的方法,不要直接操作lft、rgt字段,扩展会自动维护字段值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 10:24:04