Today we are going to create dynamic drop down menus in laravel using single table and we will give a tree structure.
We are trying to figure out to run unlimited recursive loop in view to go multiple levels but we are still in progress, so that we can get most effective output from the code we have made.
For now we are going to make simple single level drop down menu with laravel.
We are going to create similar drop down menu using laravel & using single table.
If you want to combine our past tutorial on how to create laravel drag and drop menu tutorial with this, you can make your menu more elegant with drag and drop directly from database.
Lets get started :-
What we are going to do ?
- We are going to create a table and model named
tbl_pages
. - We are going to create fields named
title and parent_id
.
Its time to create tables for our menus. Go to CMD and make model along with migration by typing tbl_pages -m
which will create mode and migration.
Add title and parent_id
in the migration in the migration file in database/migrations
folder and hit php artisan migrate
in the command-line to create fields. Take a look at my migration file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTblPagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('tbl_pages', function (Blueprint $table) { $table->increments('id'); $table->string('parent_id'); $table->string('title'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('tbl_pages'); } } |
By now your database tables will look like the image below :-
To create drop down we need to specify parent and children relationship with the menu id and parent id
, you can easily do it via model.
Laravel has provided very convenient way of adding relationship using eloquent. Take a look at my tbl_pages
model below :-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class tbl_pages extends Model { protected $table = 'tbl_pages'; public function parent() { return $this->belongsTo('App\tbl_pages', 'parent_id'); } public function children() { return $this->hasMany('App\tbl_pages', 'parent_id'); } } |
Now we have added the relationship, now its time to setup routes and controllers to send the data to view. Go to your controller in my case, i have written controller in my routes only, in routes/web.php
. Take a look below :-
1 2 3 4 |
Route::get('/',function(){ $categories = tbl_pages::with('children')->where('parent_id','=',0)->get(); return view('menu',['categories'=>$categories]); }); |
Now we already specified our controllers in routes/web.php
. Now, its time to fetch the data from views.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <link rel="stylesheet" href="{{url('public/css/bootstrap.min.css')}}"> <link rel="stylesheet" href="{{url('public/css/font-awesome.min.css')}}"> </head> <body> <div class="container"> <nav class="navbar navbar-default" role="navigation"> <ul class="nav navbar-nav navbar-left"> @foreach($categories as $item) @if($item->children->count() > 0) <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> {{$item->title}} <b class="caret"></b></a> <ul class="dropdown-menu"> @foreach($item->children as $submenu) <li><a href="#">{{$submenu->title}}</a></li> @endforeach </ul> </li> @else <li><a href="">{{$item->title}}</a></li> @endif @endforeach </ul> </nav> </div> <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.1.1.min.js"></script> <script src="{{url('public/js/bootstrap.min.js')}}"></script> </body> </html> |
The Final Code:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTblPagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('tbl_pages', function (Blueprint $table) { $table->increments('id'); $table->string('parent_id'); $table->string('title'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('tbl_pages'); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class tbl_pages extends Model { protected $table = 'tbl_pages'; public function parent() { return $this->belongsTo('App\tbl_pages', 'parent_id'); } public function children() { return $this->hasMany('App\tbl_pages', 'parent_id'); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php use App\tbl_menus; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | This file is where you may define all of the routes that are handled | by your application. Just tell Laravel the URIs it should respond | to using a Closure or controller method. Build something great! | */ Route::get('/',function(){ $categories = tbl_pages::with('children')->where('parent_id','=',0)->get(); return view('menu',['categories'=>$categories]); }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <link rel="stylesheet" href="{{url('public/css/bootstrap.min.css')}}"> <link rel="stylesheet" href="{{url('public/css/font-awesome.min.css')}}"> </head> <body> <div class="container"> <nav class="navbar navbar-default" role="navigation"> <ul class="nav navbar-nav navbar-left"> @foreach($categories as $item) @if($item->children->count() > 0) <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> {{$item->title}} <b class="caret"></b></a> <ul class="dropdown-menu"> @foreach($item->children as $submenu) <li><a href="#">{{$submenu->title}}</a></li> @endforeach </ul> </li> @else <li><a href="">{{$item->title}}</a></li> @endif @endforeach </ul> </nav> </div> <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.1.1.min.js"></script> <script src="{{url('public/js/bootstrap.min.js')}}"></script> </body> </html> |
If you have any problem be sure to leave it in the comments. We would be happy to help.
Rajaraman says
Hi.. This is working good for single level . I need multiple level with recursive loop. kindly share me any idea. Thanks in advance.
SNK says
Yes, you could do multiple dropdowns too check out https://codeinhouse.com/create-multi-level-dynamic-menu-in-laravel/. I got issues with my designs so I didn’t used it or myself in one of my projects.