AppDividend
Latest Code Tutorials

Nested Set in Laravel Tutorial

2 271

Get real time updates directly on you device, subscribe now.

Nested Set in Laravel is the today’s topic. The nested set model is to number the nodes according to a tree traversal, which visits each node twice, assigning numbers in the order of visiting, and at both visits. That leaves two numbers for each node, which are stored as two attributes. Querying becomes inexpensive: hierarchy membership can be tested by comparing these numbers. Updating requires renumbering and is therefore expensive.

What is Nested Set

Nested sets or Nested Set Model(NSM) is the way to store the hierarchical data in a relational table efficiently.

Usecase

NSM shows good performance when the tree is rarely updated. It is created to be fast for getting related nodes.

It is ideally suited for building multi-depth menu or categories for the shop.

Relationships

Nested Set is a Tree structure filled with different nodes. So their relationships are the following with each other.

  • Node belongs to parent
  • Node has many children
  • Node has many ancestors
  • Node has many descendants

Nested Set in Laravel with an Example

We will start this Laravel 5.6 Nested Set Tutorial by installing the Framework using the following command.

Step 1: Install Laravel.

I am using Laravel Valet. So, I need to type the following command to create a project.

laravel new nestedset

If you are not using any of the Homestead or Valet, then you can pull it using this command.

composer create-project laravel/laravel nestedset --prefer-dist

After installing, go into the project folder.

cd nestedset

Configure the database in the .env file.

Step 2: Install laravel-nestedset composer package.

You can find the official Github Library here.

We need to type the following command to pull it through composer.

composer require kalnoy/nestedset

Okay, so that is done, now we need to configure it.

First of all, we are trying to build an e-commerce shop. So it is the perfect scenario, where we can use the Nested Set because we have first Categories then Subcategories and the sub-subcategories and so on. So We are trying to make a list in which, the root is the primary Category, and then all its children are a subcategory.

Step 3: Create a model and database migration.

In the terminal, type the following command.

php artisan make:model Shop -m

So, it will generate the model as well as migration file. 

Now, in the migration file, we need to add some extra columns that are provided by Nested Set library.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Kalnoy\Nestedset\NestedSet;

class CreateShopsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('shops', function (Blueprint $table) {
            $table->increments('id');
            $table->string('category_name');
            NestedSet::columns($table);
            $table->timestamps();
        });
    }

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

So, this shops table contain the category_name and Nested Set columns.

Now, migrate the table using the following command.

php artisan migrate

We can see that in our shops’ table there are three columns, which is related to Nested Set.

  1. _lft
  2. _rgt
  3. parent_id

Nested Set in Laravel

 

Step 3: Seed the Database.

Related Posts
1 of 33

For this example, I am not creating the Dynamic data, but I am building the static data and then feed that into the database. 

So first, create the Seeder file using the following command.

php artisan make:seeder ShopTableSeeder

Okay, now write the following code inside ShopTableSeeder.php file.

<?php

use Illuminate\Database\Seeder;

class ShopTableSeeder extends Seeder
{
    public function run()
    {
        $shops = [
            [
                'category_name' => 'Books',
                    'children' => [
                        [    
                            'category_name' => 'Comic Book',
                            'children' => [
                                    ['category_name' => 'Marvel Comic Book'],
                                    ['category_name' => 'DC Comic Book'],
                                    ['category_name' => 'Action comics'],
                            ],
                        ],
                        [    
                            'category_name' => 'Textbooks',
                                'children' => [
                                    ['category_name' => 'Business'],
                                    ['category_name' => 'Finance'],
                                    ['category_name' => 'Computer Science'],
                            ],
                        ],
                    ],
                ],
                [
                    'category_name' => 'Electronics',
                        'children' => [
                        [
                            'category_name' => 'TV',
                            'children' => [
                                ['category_name' => 'LED'],
                                ['category_name' => 'Blu-ray'],
                            ],
                        ],
                        [
                            'category_name' => 'Mobile',
                            'children' => [
                                ['category_name' => 'Samsung'],
                                ['category_name' => 'iPhone'],
                                ['category_name' => 'Xiomi'],
                            ],
                        ],
                    ],
                ],
        ];
        foreach($shops as $shop)
        {
            \App\Shop::create($shop);
        }
    }
}

We are inserting the static array into the Database. In the real-time project, we need to do it dynamically, but for this example, I am just using a static array.

Now, go to the DatabaseTableSeeder.php file and add the following code.

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(ShopTableSeeder::class);
    }
}

Go to the terminal and seed using the following command.

php artisan db:seed

 

Laravel Nested Set Tutorial

Step 4: Create Routes and Controller.

Okay, go to the terminal and create a ShopController.php file.

php artisan make:controller ShopController

So, it will create and now write the following code inside it.

<?php

namespace App\Http\Controllers;

use App\Shop;
use Illuminate\Http\Request;

class ShopController extends Controller
{
    public function index()
    {
        $shops = Shop::get()->toTree();
        return view('shop', compact('shops'));
    }
}

So, what it will do is, we get all the data in the tree format, on which we can call the children method and we can display the exact hierarchical data into the view. 

We have not created shop view yet, but we will do that in a minute. But first, let us create the route inside the web.php file.

// web.php

Route::get('/', 'ShopController@index');

Step 5: Display the Hierarchical data into the View.

Now, we have got the data, we just need to pass that data into the View and display the data according to a parent-child relationship.

Inside the views folder, create one folder called layout and inside that folder, create one file called app.blade.php.

Write the following code inside the app.blade.php file.

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
@include('layouts.partials._head')
<body>
    <div id="app">
    <main class="py-4">
        @yield('content')
    </main>
    </div>
</body>
</html>

We have not created the partials folder, so let us create that inside layout folder.

Inside partials folder, create a file called _head.blade.php file.

<!-- _head.blade.php  -->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600" rel="stylesheet" type="text/css">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>

Now, finally create one file inside views folder called shop.blade.php.

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="card">
        <div class="row">
            <div class="card-body">
                @foreach($shops as $shop)
                <div class="col-md-12">
                    <h3>{{ $shop->category_name }}</h3>
                    <hr />
                    <div class="row">
                        @foreach($shop->children as $cats)
                        <div class="col-md-4">
                            <h4>{{ $cats->category_name }}</h4>
                            <hr />
                            @foreach($cats->children as $cat)
                            <h5>{{$cat->category_name}}</h5>
                            @endforeach
                        </div>
                        @endforeach
                    </div>
                </div>
                @endforeach
            </div>
        </div>
    </div>
</div>
@endsection

Now, save the file and go to the browser and hit the root URL and in my case, it is http://nestedset.test

You will see something like this.

Laravel 5.6 Nested Set Model Tutorial

 

So, that means, you are now getting the data based on your parent category. See how cool is that, we have not write any extra code, just use that package and we are done.

In our example, our main categories are two

  1. Books
  2. Electronics

Now, Books subcategories are the following.

  1. Comic Book
  2. Text Book

Electronics subcategories are the following.

  1. TV
  2. Mobile

We can further go into the recursion if there are more subcategories.

We can use this hierarchy to build the Mega menu for the Shopping Categories.

So this is the basic example of Nested Set Model.

Finally, Nested Set in Laravel Tutorial is over. Thanks for the taking.

2 Comments
  1. Morteza says

    Hi tnx for topic.
    when i run seed i got this error
    [ErrorException]
    preg_replace(): Parameter mismatch, pattern is a string while replacement is an array

  2. Morteza says

    In Shop.php


    use Kalnoy\Nestedset\NodeTrait;

    class Shop extends Model {
    use NodeTrait;
    }

Leave A Reply

Your email address will not be published.