Laravel无限级分类树形结构:多级分类展示实现方案问询
Hey there! Let's walk through how to display your nested categories (including all levels of subcategories) in Laravel step by step. Since you already have your table and model ready, we'll focus on the core logic to fetch and render the tree structure.
First, just to align—assuming your categories table has these basic fields (since you mentioned it's a simple setup):
id: Primary keyname: Category nameparent_id: Foreign key linking to the parent category (set to0ornullfor top-level categories)
In your Category model, define a relationship to fetch child categories, plus a recursive method to pull all nested levels:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { // Define the relationship to child categories public function children() { return $this->hasMany(Category::class, 'parent_id'); } // Recursive method to fetch all nested children public function getTree() { // Load children recursively using the same method return $this->children()->with('tree')->get(); } }
In your controller (e.g., CategoryController), grab all top-level categories along with their full nested tree:
namespace App\Http\Controllers; use App\Models\Category; use Illuminate\View\View; class CategoryController extends Controller { public function index(): View { // Get all top-level categories (parent_id = 0) with their full nested tree $categories = Category::where('parent_id', 0)->with('tree')->get(); return view('categories.index', compact('categories')); } }
The cleanest way to render nested categories is to use a recursive Blade partial.
First, create a partial view at resources/views/categories/_category_list.blade.php:
<ul> @foreach($categories as $category) <li> {{ $category->name }} <!-- If the category has children, recursively include the partial --> @if($category->children->isNotEmpty()) @include('categories._category_list', ['categories' => $category->children]) @endif </li> @endforeach </ul>
Then, in your main view (resources/views/categories/index.blade.php), include the partial and pass the top-level categories:
<h1>All Categories</h1> @include('categories._category_list', ['categories' => $categories])
If you prefer to fetch all categories first and build the tree in memory (good for small datasets), add this static method to your Category model:
public static function buildTree(): \Illuminate\Database\Eloquent\Collection { $allCategories = static::all(); return $allCategories->where('parent_id', 0)->map(function ($category) use ($allCategories) { $category->children = self::buildChildTree($category, $allCategories); return $category; }); } private static function buildChildTree(Category $category, $allCategories): \Illuminate\Database\Eloquent\Collection { return $allCategories->where('parent_id', $category->id)->map(function ($child) use ($allCategories) { $child->children = self::buildChildTree($child, $allCategories); return $child; }); }
Then in your controller, just call:
$categories = Category::buildTree();
If you have a huge number of categories, the recursive query approach might hit performance limits. For that, consider using the Nested Set Model—there's a popular Laravel package that simplifies this, letting you fetch the entire tree in a single query and handle nested operations efficiently.
内容的提问来源于stack exchange,提问作者Kamilos

