В этом уроке мы начнем создавать админку на 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;
После этого можете проверить работу валидации
Статья дополняется...