Админка: создание и изменение категории (Урок 6)

В этом уроке мы начнем создавать админку на Laravel в которой будет работать администратор сайта. В админке нашего блога у администратора должна быть возможность управлять категориями наших постов, создавать их, редактировать и удалять.

Для начала создадим контроллер категорий, написав в консоли следующую команду:

php artisan make:controller Blog/Admin/CategoryController --resource

После этого в файле routes\web.php сделаем следующий маршрут:

$groupData = [
	'namespace' => 'Blog\Admin',
	'prefix' => 'admin/blog',
];
Route::group($groupData, function(){
	$methods = ['index','edit','store','update','create',];
	Route::resource('categories','CategoryController')->only($methods)->names('blog.admin.categories');
});

Посмотрите внимательно данный код, я кратко поясню, что тут за что отвечает, в массиве $groupData мы указали путь к папке, где наш контроллер 'namespace' => 'Blog\Admin' и указали префикс, т.е. адрес по которому мы будем обращаться в браузере 'prefix' => 'admin/blog'. В массиве $methods мы указали методы с которыми будем работать.

Откроем файл app\Http\Controllers\Blog\Admin\CategoryController.php и удалим лишние методы: destroy(), show()

В папке \app\Http\Controllers\Blog\Admin создайте файл BaseController.php с таким содержимым

namespace App\Http\Controllers\Blog\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Blog\BaseController as GuestBaseController;

abstract class BaseController extends GuestBaseController
{
   
}

Это базовый класс в админке блога, от которого мы будет наследоваться. В файле app\Http\Controllers\Blog\Admin\CategoryController.php в начале после namespace добавьте:

use App\Models\BlogCategory

И измените строчку class CategoryController extends Controller на это:

class CategoryController extends BaseController

Выводим список категорий блога

В методе index() внесите следующий код:

public function index()
{
	$paginator = BlogCategory::paginate(5);
	return view('blog.admin.category.index', compact('paginator'));		
}

Строчка $paginator = BlogCategory::paginate(7); говорит о том, что у нас будет постраничная навигация с выводом элементов по 7 штук, если вам надо вывести все записи используйте эту строчку $paginator = BlogCategory::all();

Строчка return('blog.admin.category.index', compact('paginator')); говорит о том, что мы передаем в представление (в файл шаблона грубо говоря), наши данные и говорим, что это надо вывести. Файл resources\views\blog\admin\category\index.blade.php у нас еще не создан, поэтому давайте его создадим его и вставим в него такой код:

@extends('layouts.app')

@section('content')
	<div class="container">
		<div class="col-md-12">
			<nav class="navbar bg-white">
				<a class="btn btn-primary" href="{{route('blog.admin.categories.create')}}">Добавить</a>
			</nav>
			<div class="card-body bg-white">
				<table class="table table-hover">
					<thead>
						<tr>
							<th>#</th>
							<th>Категория</th>
							<th>Родитель</th>
						</tr>
					</thead>
					<tbody>
					@foreach($paginator as $item)	
						<tr>
							<td>{{$item->id}}</td>
							<td>
								<a href="{{route('blog.admin.categories.edit', $item->id)}}">
									{{$item->title}}
								</a>
							</td>
							<td>{{$item->parent_id}}</td>
						</tr>
					@endforeach
					</tbody>
				</table>
			</div>
		</div>
		
		@if($paginator->total() > $paginator->count())
		
			<div class="col-md-12">
				<div class="card-body bg-white">
				{{$paginator->links()}}
				</div>
			</div>
		
		@endif
	</div>
@endsection

Вам необязательно копировать мой код, можете сверстать так как считаете нужным, главное не забудьте про ключевые данные, которые отвечают за вывод информации.

Поясню некоторые моменты, например:
ссылка {{route('blog.admin.categories.create')}} - отправит нас на страницу ваш_сайт/admin/blog/categories/create за эту страницу у нас отвечает метод create() в файле \app\Http\Controllers\Blog\Admin\CategoryController.php
ссылка {{route('blog.admin.categories.edit', $item->id)}} - перенаправит нас на страницу /admin/blog/categories/id_категории/edit за эту страницу отвечает метод edit() в файле \app\Http\Controllers\Blog\Admin\CategoryController.php

Посмотреть результат вы можете по ссылке в браузере ваш_сайт/admin/blog/categories У меня это выглядит следующим образом:

Страница редактирования категории

Сделаем страницу редактирования, для этого в файле app\Http\Controllers\Blog\Admin\CategoryController.php в метод edit() добавьте такой код:

public function edit($id)
{
	$item = BlogCategory::findOrFail($id);
	$categoryList = BlogCategory::all();

	return view('blog.admin.category.edit', compact('item','categoryList'));
}

Строчка $item = BlogCategory::findOrFail($id); - означает, что он либо найдет в базе категорию с переданным id, либо вернет 404 ошибку.

Теперь нам надо сделать шаблон нашей страницы редактирования, создайте файл resources\views\blog\admin\category\edit.blade.php со следующим содержимым:

@extends('layouts.app')
@section('content')
	<div class="container">
		@if($errors->any())
			<div class="alert alert-danger" role="alert">
				<button type="button" class="close" data-dismiss="alert" aria-label="Close">
					<span aria-hidden="true">x</span>
				</button>
				{{$errors->first()}}
			</div>
		@endif
		@if(session('success'))
			<div class="alert alert-success" role="alert">
				<button type="button" class="close" data-dismiss="alert" aria-label="Close">
					<span aria-hidden="true">x</span>
				</button>
				{{session()->get('success')}}
			</div>
		@endif
		<div class="col-md-12 bg-white row">	
			<form method="POST" action="{{route('blog.admin.categories.update',$item->id)}}" class="col-xs-6 w-75">
			@method('PATCH')
			@csrf
			<div class="card-body">
				<div class="container-fluid">
					<div class="form-group">
						<label for="title">Заголовок</label>
						<input type="text" name="title" value="{{$item->title}}" class="form-control"/>
					</div>
					<div class="form-group">
						<label for="slug">Код</label>
						<input type="text" name="slug" value="{{$item->slug}}" class="form-control"/>
					</div>
					<div class="form-group">
						<label for="parent_id">Родитель</label>
						<select name="parent_id" class="form-control">
						@foreach($categoryList as $categoryOption)
							<option value="{{$categoryOption->id}}" @if($categoryOption->id == $item->parent_id) selected @endif >
								{{$categoryOption->title}}
							</option>
						@endforeach
						</select>
					</div>
					<div class="form-group">
						<label for="description">Описание</label>
						<textarea name="description" class="form-control">	
						{{$item->description}}
						</textarea>
					</div>
					<div class="form-group">
						<button type="submit" class="btn btn-primary">Сохранить</button>
					</div>
				</div>		
			</div>
			</form>
			<div class="card-body col-xs-6">
				<div class="container-fluid">
					<div class="form-group">
						<label for="title">ID:</label>					
						<input type="text" name="id" value="{{$item->id}}" class="form-control" disabled />
					</div>
					<div class="form-group">
						<label for="created_at">Создано</label>
						<input type="text" name="created_at" value="{{$item->created_at}}" class="form-control" disabled />
					</div>
					<div class="form-group">
						<label for="updated_at">Изменено</label>
						<input type="text" name="updated_at" value="{{$item->updated_at}}" class="form-control" disabled />
					</div>
					<div class="form-group">
						<label for="deleted_at">Удалено</label>
						<input type="text" name="deleted_at" value="{{$item->deleted_at}}" class="form-control" disabled />
					</div>
				</div>
			</div>
		</div>
	</div>
@endsection

Можете посмотреть эту страницу редактирования в браузере перейдите например по ссылке Ваш_сайт/admin/blog/categories/14/edit где 14 это id категории, которую вы хотите изменить.

Для того, чтобы при нажатии на кнопку Сохранить, у нас внеслись изменения в базу данных, нам надо внести код в файле app\Http\Controllers\Blog\Admin\CategoryController.php в методе update()

public function update(Request $request, $id)
{
	$item = BlogCategory::find($id);
	if(empty($item)){
		return back()->withErrors(['msg'=>"Запись id = [{$id}]не найдена"])->withInput();
	}

	$data = $request->all();
	$result = $item->fill($data)->save();
			
	if($result){
		return redirect()->route('blog.admin.categories.edit',$item->id)->with(['success'=>"Успешно сохранено"]);
	}else{
		return back()->withErrors(['msg'=>"Ошибка сохранения"])->withInput();
	}
}

Этой строчкой $item = BlogCategory::find($id); - мы находим нашу категорию.
Этой строчкой return back()->withErrors(['msg'=>"Запись id = [{$id}]не найдена"])->withInput(); мы возвращаем ошибку, если мы не нашли запись, надпись withInput() означает, что мы сохраняем данные, которые пользователь ввел в инпуты.
Строчкой $data = $request->all(); мы получаем данные, которые отправил пользователь, а строчкой $result = $item->fill($data)->save(); сохраняем эти данные, обратите внимание на надпись fill($data), это своего рода проверка на поля, которые можно обновлять, список этих полей надо указать в файле app\Models\BlogCategory.php следующим образом:

class BlogCategory extends Model
{  	
	protected $fillable = [
		'title',
		'slug',
		'parent_id',
		'description',
		];
}

Также нам надо сделать какую-нибудь валидацию (проверку) данных, которые вводит пользователь, для этого в консоли выполните команду:

php artisan make:request BlogCategoryUpdateRequest

После откройте файл app\Http\Requests\BlogCategoryUpdateRequest.php и внесите изменения в метод authorize()

public function authorize()
{
    return true;
}

И в метод rules()

public function rules()
{
    return [
        'title'=>'required|min:5|max:200',
		'slug'=>'max:200',
		'description'=>'string|min:3|max:500',
		'parent_id'=>'required|integer|exists:blog_categories,id',
    ];
}

Как вы наверное поняли в методе rules() мы указали правила валидации для наших полей, к примеру поле title обязательно для заполнения, должно быть не менее 5 символов и не более 200 символов, поле parent_id тоже обязательно, должно быть числовым и значение должно быть в id категории

Для того, чтобы наша валидация заработала в файле app\Http\Controllers\Blog\Admin\CategoryController.php строчку:

public function update(Request $request, $id)

замените на:

public function update(BlogCategoryUpdateRequest $request, $id)

И в начале файла после namespace App\Http\Controllers\Blog\Admin; добавьте

use App\Http\Requests\BlogCategoryUpdateRequest;

После этого можете проверить работу валидации

Статья дополняется...

Комменатрии
Анатолий 23.11.2020 14:44:17
Написано четко, понятно. Но не все работает.
Ответить
Добавить комментарий