Laravel Eloquent HasMany Recursive Relationship with Subitems
Today I’m going to show how to view items and deep level sub-items. Let’s get started:
Table of Contents
Database Migration
Create a model, migrations and controller using this command:
php artisan make:model Item -mc
Open the newly created migration file from database/migrations folder and update up()
method:
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedBigInteger('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('items');
$table->timestamps();
});
}
Now migrate the database:
php artisan migrate
Eloquent Model and Relationships
We’re going to add two relations in app/Item.php model. One for displaying level one items and another one for showing recursive items:
class Item extends Model
{
// return one level of child items
public function items()
{
return $this->hasMany(Item::class, 'parent_id');
}
// recursive relationship
public function childItems()
{
return $this->hasMany(Item::class, 'parent_id')->with('items');
}
}
Modify Controller and Define Route
Open ItemController from app\Http\Controllers and add the index()
method:
<?php
namespace App\Http\Controllers;
use App\Item;
use Illuminate\Http\Request;
class ItemController extends Controller
{
public function index() {
$items = Item::whereNull('parent_id')
->with('childItems')
->get();
return view('items', compact('items'));
}
}
Now define a route in routes/web.php for the index()
method:
Route::get('items', 'ItemController@index');
Create Views
Go to resources/views folder and create 2 files named items.blade.php and sub_items.blade.php. Then paste these codes:
<ul>
@if(count($items) > 0)
@foreach ($items as $item)
<li>{{ $item->name }}</li>
<ul>
@if(count($item->childItems))
@foreach ($item->childItems as $childItems)
@include('sub_items', ['sub_items' => $childItems])
@endforeach
@endif
</ul>
@endforeach
@endif
</ul>
<li>{{ $sub_items->name }}</li>
@if ($sub_items->items)
<ul>
@if(count($sub_items->items) > 0)
@foreach ($sub_items->items as $childItems)
@include('sub_items', ['sub_items' => $childItems])
@endforeach
@endif
</ul>
@endif
Now insert some data into items tables and run the project. Then visit http://localhost:8000/items
route to see the output. Here’s my one:
That’s it. Thanks for reading.
Md Obydullah
Software Engineer | Ethical Hacker & Cybersecurity...
Md Obydullah is a software engineer and full stack developer specialist at Laravel, Django, Vue.js, Node.js, Android, Linux Server, and Ethichal Hacking.