In this post, we will see how we can create categories and subcategories dynamically in laravel.
Run the command below to create the Category model and migration.
php artisan make:model Category -m
It will create the Category.php
in app directory and date_str_create_categories_table.php
in database/migrations directory.
Replace the code in date_str_create_categories_table.php
file with the code below.
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateCategoriesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('categories', function (Blueprint $table) { $table->bigIncrements('id'); $table->integer('parent_id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('categories'); } }
Replace the code of Category.php
with the code below.
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Category extends Model { protected $fillable = ['parent_id', 'name']; public function childs() { return $this->hasMany(Category::class, 'parent_id'); } public function parent() { return $this->belongsTo(Category::class, 'parent_id'); } }
Add the line below to web.php
Route::resource('categories', 'CategoryController');
Run the command below to create the controller. It will create CategoryController.php in app/Http/Controllers directory.
php artisan make:controller CategoryController --resource
Replace the CategoryController.php
with the code below.
<?php namespace App\Http\Controllers; use App\Category; use Illuminate\Http\Request; use App\Http\Requests\CreateCategoryRequest; class CategoryController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index(Request $request) { $categories = Category::all(); return view('categories.index')->with(compact(['categories'])); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { $categories = Category::all(); return view('categories.create')->with(compact(['categories'])); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $category = new Category; $category->name = $request->name; $category->parent_id = $request->parent_category ? $request->parent_category : 0; if ($category->save() ) { return redirect()->route('categories.index')->with(['success' => 'Category added successfully.']); } return redirect()->back()->with(['fail' => 'Unable to add category.']); } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit(Category $category) { $categories = Category::all(); return view('categories.edit')->with(compact(['category', 'categories'])); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(CreateCategoryRequest $request, Category $category) { $category->name = $request->name; $category->parent_id = $request->parent_category ? $request->parent_category : 0; if ($category->save() ) { return redirect()->route('categories.index')->with(['success' => 'Category successfully updated.']); } return redirect()->back()->with(['fail' => 'Unable to update category.']); } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy(Category $category) { if ($category->delete()) { return redirect()->back()->with(['success' => 'Category successfully deleted.']); } return redirect()->back()->with(['fail' => 'Unable to delete category.']); } }
Now we are going to create the view files.
Create the file master.blade.php
in resources/views/layouts
directory and add the code below.
<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{{ __('Category') }}</title> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <!-- jQuery library --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <!-- Latest compiled JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <ul class="nav justify-content-end"> <li class="nav-item"> <a class="nav-link" href="{{ route('categories.index') }}">{{ __('Categories') }}</a> </li> <li class="nav-item"> <a class="nav-link" href="{{ route('categories.create') }}">{{ __('Create category') }}</a> </li> </ul> <main class="py-4"> @yield('content') </main> </body> </html>
Create the file index.blade.php
in resources/views/categories
directory and copy the below code.
@extends('layouts.master') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-10"> <div class="card"> <div class="card-header"> Categories <a href="{{ route('categories.create') }}" class="btn btn-primary float-right">Create category</a> </div> <div class="card-body"> @include('partials.alerts') <table class="table"> <thead> <tr> <th>Category Name</th> <th>Parent Category</th> <th>Actions</th> </tr> </thead> <tbody> @foreach($categories as $category) <tr> <td>{{ $category->name}}</td> <td> @if ($category->parent) {{ $category->parent->name}} @endif </td> <td> <a href="{{ route('categories.edit', ['category'=> $category->id]) }}" class="btn btn-xs btn-info">Edit</a> <form action="{{ route('categories.destroy', ['category'=> $category->id]) }}" method="POST" style="display: inline-block;"> @method('DELETE') @csrf <button class="btn btn-xs btn-danger">Delete</button> </form> </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </div> </div> @endsection
Create the file create.blade.php
in resources/views/categories
directory and add the code below.
@extends('layouts.master') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-10"> <div class="card"> <div class="card-header"> Create Category <a href="{{ route('categories.create') }}" class="btn btn-primary float-right">Create category</a> </div> <div class="card-body"> @include('partials.alerts') <form action="{{ route('categories.store') }}" method="post"> {{ csrf_field() }} <div class="form-group"> <label for="name">Category Name:</label> <input type="name" class="form-control" id="name" placeholder="Enter name" name="name"> <span class="text-danger">{{ $errors->first('name') }}</span> </div> <div class="form-group"> <label for="parent_category">Parent Category:</label> <select class="form-control" name="parent_category"> <option value="">Select a category</option> @foreach($categories as $category) <option value="{{ $category->id }}">{{ $category->name }}</option> @endforeach </select> <span class="text-danger">{{ $errors->first('parent_category') }}</span> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> </div> @endsection
Create the file edit.blade.php
in resources/views/categories
directory and add the code below.
@extends('layouts.master') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-10"> <div class="card"> <div class="card-header"> Edit Category <a href="{{ route('categories.create') }}" class="btn btn-primary float-right">Create category</a> </div> <div class="card-body"> @include('partials.alerts') <form action="{{ route('categories.update', ['category'=>$category->id] ) }}" method="post"> {{ csrf_field() }} <input name="_method" type="hidden" value="PUT"> <div class="form-group"> <label for="name">Category Name:</label> <input type="name" class="form-control" id="name" name="name" value="{{ $category->name }}"> <span class="text-danger">{{ $errors->first('name') }}</span> </div> <div class="form-group"> <label for="pwd">Parent Category:</label> <select class="form-control" name="parent_category"> <option>Select a category</option> @foreach($categories as $category) <option value="{{ $category->id }}">{{ $category->name }}</option> @endforeach </select> <span class="text-danger">{{ $errors->first('parent_category') }}</span> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> </div> </div> </div> @endsection
Run command php artisan serve
and run the url http://127.0.0.1:8000/categories
in browser.
I hope it will helps you, if you have any query feel free to comment below.
CreateCategoryRequest is missing