В этой статье мы будем рассматривать как можно создать динамические категорий и подкатегорий в Laravel.
Создание модели и миграций к ней
Запустите команду ниже для создания модели Category и миграций к ней.
php artisan make:model Category -m
Эта команда создаст Category.php в каталоге app и файл миграций date_str_create_categories_table.php
в каталоге database/migrations.
Замените код в файле date_str_create_categories_table.php на следующий код ниже.
<?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');
}
}
Замените код в Category.php на код который расположен ниже.
<?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');
}
}
Работа с маршрутами
Добавьте строчку ниже в файл web.php.
Route::resource('categories', 'CategoryController');
Работа с контроллерами
Запустите команду ниже для создания контроллера. Эта команда создаст CategoryController.php в директорий app/Http/Controllers.
php artisan make:controller CategoryController --resource
Замените код в файле CategoryController.php
на код ниже:
<?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.']);
}
}
Создание представлений
Сейчас мы собираемся создать файлы представлений.
Создадим master.blade.php в директорий resources/views/layouts и добавим код ниже.
<!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>
Создайте файл index.blade.php в директорий resources/views/categories и копируйте в него код ниже.
@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.blade.php в директорий resources/views/categories и добавьте в него код ниже.
@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
Создайте файл edit.blade.php в директорий resources/views/categories и добавьте код ниже.
@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
Запустите команду php artisan serve
и перейдите в строку браузера http://127.0.0.1:8000/categories .
Надеюсь статья поможет вам.