How to define Laravel HasMany Recursive Relationship with Subitems

Do you want to have parent child level relationship into your laravel project? then you are at right place this tutorial will give you everything you need to build parent child Recursive Relationship in Laravel using Eloquent HasMany Relationship method.

Recommended – How to Implement Laravel Eloquent One-to-Many Relationship

Let’s get started

Create Database Table Structure

Create new database model and a migration file which we use to define our categories table

php artisan make:model Categories -m

Add following columns for categories table

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->unsignedBigInteger('category_id')->nullable();
            $table->timestamps();

            $table->foreign('category_id')
                ->references('id')
                ->on('categories')
                ->onDelete('set null');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

Migrate the database

php artisan migrate

laravel6 git:(master) ✗ php artisan migrate
Migrating: 2019_09_09_164026_create_categories_table
Migrated: 2019_09_09_164026_create_categories_table (0.07 seconds)

Just so you understand the table schema if you see here we have single table where are going to store parent as well as child categories.

We have used category_id column as parent category indicator for corresponding row.

If the category_id column is empty which means given category is a root category it does not have any parent items.

So all sub categories will have category id in it and finally if the given category is deleted then the sub category will become root category.

Add few records according to your need in categories table, for this demo I am going to add dummy items like showing below

Categories table with parent child items

Define Eloquent model Relationship

This is important part of this tutorial and this is the main reason of writing this tutorial because it is the actual solution to have Laravel HasMany Recursive Relationship in your project.

Open Categories model from app folder and define following methods:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Categories extends Model
{
    // this relationship will only return one level of child items
    public function categories()
    {
        return $this->hasMany(Categories::class, 'category_id');
    }

    // This is method where we implement recursive relationship
    public function childCategories()
    {
        return $this->hasMany(Categories::class, 'category_id')->with('categories');
    }
}

If we try to get records like this

Categories::with('categories')->get() 

It will returns us only one level of child items and here is the magic if you call

Categories::with('childCategories')->get();

It is going to give us all items with recursive relationship.

Next’s lets see how we can show this relationship using Laravel Blade View

Create new Controller and Define Route

We will this control to fetch categories from the database using our Categories eloquent model and pass it to the laravel blade file

php artisan make:controller CategoriesController

Define getCategories method in CategoriesController, this is the method where we are going to fetch all the categories with parent child relationship.

/app/Http/Controllers/CategoriesController.php

<?php

namespace App\Http\Controllers;

use App\Categories;

class CategoriesController extends Controller
{
    public function getCategories()
    {
        $categories = Categories::whereNull('category_id')
            ->with('childCategories')
            ->orderby('title', 'asc')
            ->get();
        return view('categories', compact('categories'));
    }
}

Define route to get categories under web.php file:

Route::get('/get-categories', 'CategoriesController@getCategories');

Create Parent View and Child View:

This is also and important part while your displaying recursive categories list, we are going to need two views here first is the one which display the first level parent categories and second view is the one which is going to list out all the child level categories.

Create new file called categories.blade.php under views folder

/resources/views/categories.blade.php

     <ul>
        @if(count($categories) > 0)
            @foreach ($categories as $category)
                <li>{{ $category->title }}</li>
                <ul>
                    @if(count($category->childCategories))
                        @foreach ($category->childCategories as $subCategories)
                            @include('sub_categories', ['sub_categories' => $subCategories])
                        @endforeach
                    @endif
                </ul>
            @endforeach
        @endif
    </ul>

As you can see here in the above example I have added foreach loop to loop over the $categories array and then next for sub level I have included sub_categories view using @include

Go ahead and create sub view called sub_categories.blade.php

/resources/views/sub_categories.blade.php

<li>{{ $sub_categories->title }}</li>
@if ($sub_categories->categories)
    <ul>
        @if(count($sub_categories->categories) > 0)
            @foreach ($sub_categories->categories as $subCategories)
                @include('sub_categories', ['sub_categories' => $subCategories])
            @endforeach
        @endif
    </ul>
@endif

So here is the another magic happening first we are looping from the $sub_categories->categories array and next we have included same view itself so it will keep on going to iterate over until the last child item form the array.

So this how we can implement Eloquent HasMany Recursive Relationship with Subitems in Laravel Framework.

If you access /get-categories route you should see following parent child level output:

Laravel Eloquent HasMany Recursive Relationship with Subitems

If you get any question specify to this tutorial let me know using comment box below.

Yogesh Koli

Software engineer & Blogger lives in India, has 6+ years of experience working with the front-end and back-end web app development.

Recent Posts

Complete guide of using Laravel 6 Eloquent Subquery Enhancements

Learn How to use laravel frameworks new improved feature called Eloquent Subquery and get example…

10 months ago

3 Useful examples of using Array Map function in PHP – Best Practices

Learn how to use php array map function with easy and essential tutorial to modify…

10 months ago

Working with PHP Array Filter Function – Best Practices

Learn how to use php array filter function with easy and essential tutorial to filter…

10 months ago

How to add Access Modifiers with Constructor Parameters in TypeScript

Want to know how to refactor your Typescript class, Learn here utilising Typescript of the…

10 months ago

What is Access Modifiers and how to use Access Modifiers in TypeScript ?

What is Access Modifiers in typescript, how to use Access Modifiers, when to use them,…

10 months ago

Top 10 Super Useful Packages to Improve Laravel applications in 2019

This tutorial provide ultimate list of package those are top 10 on packagist and super…

10 months ago