How to Make Categories Inside Categories in Laravel (Unlimited Levels)

Sometimes in your Laravel app, you need to create categories that can have subcategories. And those subcategories can also have more subcategories. This is called nested categories, and it can go to any level — 2, 3, 5, or even more.

In this post, I will show you how to create this in a clean and simple way using Laravel.


Problem Example

You are building a blog or an online shop.

  • Category: Programming

    • Subcategory: PHP

      • Subcategory: Laravel

        • Subcategory: Livewire

This is what we call a tree structure — one item has children, and those children have more children.


Step 1: Create Database Table

We will use a very simple structure. Just add a parent_id column in your categories table. This is called the Adjacency List method.

Table Example

idnameparent_id
1ProgrammingNULL
2PHP1
3Laravel2
4Vue.js1
5Livewire3

This means:

  • Programming is a top-level category (no parent).

  • PHP is a child of Programming.

  • Laravel is a child of PHP.

  • Livewire is a child of Laravel.


Step 2: Laravel Model

In your Category.php model, define two relationships.

class Category extends Model

{

public function parent()

{

return $this->belongsTo(Category::class, 'parent_id');

}

public function children()

{

return $this->hasMany(Category::class, 'parent_id');

}

}

This helps you get the parent and children of any category easily.


Step 3: Recursive Relationship

To go deep into children of children, add a recursive function like this:

public function childrenRecursive()

{

return $this->children()->with('childrenRecursive');

}

Now you can get all levels of subcategories.


Step 4: Get Tree in Controller

In your controller, get only the top-level categories with all their children:

$categories = Category::with('childrenRecursive')->whereNull('parent_id')->get();

Step 5: Show in Blade View

In your main Blade file:

<ul>

@foreach($categories as $category)

<li>

{{ $category->name }}

@if($category->childrenRecursive->count())

@include('partials.category-children', ['children' => $category->childrenRecursive])

@endif

</li>

@endforeach

</ul>

Create a file called partials/category-children.blade.php:

<ul>

@foreach($children as $child)

<li>

{{ $child->name }}

@if($child->childrenRecursive->count())

@include('partials.category-children', ['children' => $child->childrenRecursive])

@endif

</li>

@endforeach

</ul>

This will show all categories in a nice tree view — no matter how many levels deep.

Summary Table

MethodEasy to useGood for small projectsNeeds a package
Adjacency ListYesYesNo
Nested SetNoNo (good for large apps)Yes
Materialized PathNoSometimesNo

We used the Adjacency List, which is the easiest and works well for most apps.


Final Words

If you are a beginner or working on a small to medium project, this method is best. It is simple and works well with Laravel Eloquent.

Later, if your app grows, you can explore more advanced methods like nested sets or materialized paths.

Let me know if you need help with code or want me to write about showing this in Vue or Livewire.

0
Subscribe to my newsletter

Read articles from Rameez Karamat Bhatti directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rameez Karamat Bhatti
Rameez Karamat Bhatti

I am a full-stack developer currently working with PHP, Laravel, Tailwind CSS, and Livewire. I also work extensively with Inertia.js to build seamless single-page applications using Vue.js and Laravel. I have experience building reactive frontends with Vue.js and React, and robust backends with REST APIs. I am highly proficient in MySQL, MongoDB, and also comfortable working with PostgreSQL for relational data projects. My focus is on clean, scalable code and building user-focused digital products.