如何在Laravel导航菜单中展示分类-子分类层级结构
在Laravel中实现分类与子分类的导航菜单层级结构
嘿,这个需求我之前做项目的时候刚好碰到过,咱们一步步来搞定它~首先得提个小细节:你给的数据里id=1的分类parent_id是1,这会造成自引用循环哦,建议把顶级分类的parent_id改成0或者null,这样逻辑更通顺,下面我就按这个修正后的逻辑来给你方案哈
1. 给Category模型添加上关联关系
我们需要让模型能识别父分类和子分类的关联,打开你的App\Models\Category.php,添加以下代码:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { // 定义子分类关联:一个分类可以有多个子分类 public function children() { return $this->hasMany(Category::class, 'parent_id'); } // 可选:定义父分类关联,方便反向查询 public function parent() { return $this->belongsTo(Category::class, 'parent_id'); } }
2. 在控制器里获取树形结构的分类数据
接下来要把扁平的分类数据转换成树形结构,方便视图渲染,这里提供两种方式,你可以按需选择:
方式一:预加载固定层级的子分类(适合层级确定的情况)
如果你的分类最多只有3层(比如顶级→二级→三级),可以直接用嵌套预加载:
namespace App\Http\Controllers; use App\Models\Category; use Illuminate\Http\Request; class CategoryController extends Controller { public function index() { // 获取所有顶级分类(parent_id=0),并预加载二级、三级子分类 $categories = Category::where('parent_id', 0) ->with('children.children') ->get(); return view('layouts.navigation', compact('categories')); } }
方式二:递归生成完整树形结构(适合层级不确定的情况)
如果分类层级不固定,比如可能有四级、五级,那就用递归函数来构建树形数组:
namespace App\Http\Controllers; use App\Models\Category; use Illuminate\Http\Request; class CategoryController extends Controller { public function index() { $allCategories = Category::all(); // 递归生成树形结构,默认从parent_id=0的顶级分类开始 $treeCategories = $this->buildTree($allCategories); return view('layouts.navigation', compact('treeCategories')); } // 递归构建树形结构的辅助函数 private function buildTree($categories, $parentId = 0) { $tree = []; foreach ($categories as $category) { if ($category->parent_id == $parentId) { // 递归查找当前分类的子分类 $children = $this->buildTree($categories, $category->id); if ($children) { $category->children = $children; } $tree[] = $category; } } return $tree; } }
3. 在Blade视图里递归渲染导航菜单
最后一步就是把树形数据渲染成带层级的导航菜单,我们可以用Blade的@include实现递归渲染:
第一步:主视图中的导航容器
比如在你的布局文件resources/views/layouts/navigation.blade.php中:
<nav class="navbar"> <ul class="main-menu"> <!-- 循环顶级分类,调用子视图渲染每个分类项 --> @foreach($categories as $category) @include('partials.category-menu-item', ['category' => $category]) @endforeach </ul> </nav>
第二步:创建递归渲染的子视图
新建resources/views/partials/category-menu-item.blade.php,内容如下:
<li class="menu-item"> <!-- 分类链接 --> <a href="{{ route('categories.show', $category->id) }}">{{ $category->title }}</a> <!-- 如果当前分类有子分类,递归渲染子菜单 --> @if($category->children->isNotEmpty()) <ul class="sub-menu"> @foreach($category->children as $child) @include('partials.category-menu-item', ['category' => $child]) @endforeach </ul> @endif </li>
这样不管你的分类有多少层级,都会自动递归渲染出来,最后你只需要给.main-menu、.sub-menu这些类加CSS样式,调整缩进、下拉效果就可以啦~
内容的提问来源于stack exchange,提问作者soy dara
相关产品推荐
相关产品推荐

