10. Обновление и изменение категорий

19 Июня 2020 02:02 (Редактировано: 21 Июня 2020 04:08)

За обновление информации в категоирях в админке будет отвечать метод update в контроллере CategoryController. Путь: project.loc\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();
    }
}

По порядку:

  1. 1 строка. Передаем первым параметром в метод объект класса Request. Этот объект предназначен для работы с входящими данными. В нем содержится разная инфа о типах запроса (ajax/не ajax), ip адрес и многое другое...
  2. 1 строка. Передаем вторым параметром id категории. По этому идентификатору будет строиться маршрут для обновления данных, в маршрутах он выглядит так: 
    |        | PUT|PATCH | admin/blog/categories/{category}      | blog.admin.categories.update | App\Http\Controllers\Blog\Admin\CategoryController@update 

    В файле представления edit.blade.php в блоке формы мы, также, передаем директиву, что это метод PATCH для Laravel.

  3. 3 - 6 строки. Используем метод find для поиска в базе категории с переданным идентификатором, если такая есть - вернется объект класса BlogCategory, если нет - null; Поэтому если срабатывает empty мы переадресуем посетителя на предыдущю страницу (там где была нажата кнопка) с передачей информации об ошибке с помощью метода withErrors c текстом ошибки и метода withInputs, чтобы те данные, которые уже были введены в форму не пропали после редиректа и вернулись, а уже в представлении можно вывести проверку на то были ли возвращены такие данные. Таким образом, при ошибке все, что было введено в форму - останется. Поэтому вносим поправки в файл item_edit_main_col.blade.php в самый низ где textarea формы и придаем ей следующий вид:

    <textarea name="description" id="description" rows="3" class="form-control">
        {{old('description', $item->description)}}
    </textarea>

    С помощью хелперской функции old мы говорим какой ключ искать в старом инпуте если он придет. Если ключ не найден или не пришли данные то мы подставляем данные старые из базы данных.

    Можно по эксперементировать и попробовать убрать withInput и посмотреть что будет происходить. Также можно посмотреть результат в дебагбаре

  4. 8 строка. Получаем все из объекта Request с помощью метода all(). Также есть метод input(), который, вероятно, получает только значения полей формы.
  5. 9 строка. У объекта BlogCategory есть унаследованный от Model метод fill(), который заполнит объект данными и методом save() запишет их в базу. А ответ будет true/false, который будет положен в переменную $result. Чуть дальше заполним BlogCategory данными, взаимодействующими с этим методом.
  6. 10 - 15 строки. Поведение в зависимости от того, что в $result.
    • Если true - шлем по маршруту с  с сообщением success с помощью хелперской функции redirect().
    • Если false - возвращаем на предыдущую страницу с сообщением об ошибке  и возвращением значений инпутов с помощью хелперской функции back().

Обновляем класс BlogCategory

Путь: poligon.local\app\Models\BlogCategory.php.

<?php

namespace App\Models;

use Eloquent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * BlogCategory
 *
 * @mixin Eloquent
 */

class BlogCategory extends Model
{
    use SoftDeletes;

    protected $fillable = ['title', 'slug', 'parent_id', 'description'];
}
  1. 7 строка. Добавляем SoftDeletes;
  2. 17 строка. Подключаем SoftDeletes.
  3. 19 строка. Добавляем свойство $fillable, которое обозначит с какими полями работать. то есть, с помощью метода fill в CategoryController(метод update) будут сохранены только указанные поля.

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

Внесение правок в директории

  1. Переименовываем директорию project.loc\resources\views\blog\admin\category в categories. Полный путь должен выглядеть вот так: project.loc\resources\views\blog\admin\categories.
  2. Переименовываем подключаемые файлы в представлении в project.loc\resources\views\blog\admin\categories\edit.blade.php. Там два include, у которых в пути category, переделываем в categories соответственно.
  3. Переименовываем в файле poligon.local\app\Http\Controllers\Blog\Admin\CategoryController.php в методе edit() путь возвращаемого представления с category на categories. Также смотрим метод index() который нам выводит список категорий, в нем тоже меняем возвращаемое представление с category на categories.

Проверяем, чтобы все работало!

Добавляем сообщения об ошибке в представление

Путь: poligon.local\resources\views\blog\admin\categories\edit.blade.php.

@extends('layouts.app')

@section('content')
    @php /** @var \App\Models\BlogCategory $item */ @endphp
    <form method="POST" action="{{ route('blog.admin.categories.update', $item->id) }}">
        @method('PATCH')
        @csrf
        <div class="container">
            @php
            /** @var \Illuminate\Support\ViewErrorBag $errors */
            @endphp
            @if($errors->any())
                <div class="row justify-content-center">
                    <div class="col-md-11">
                        <div class="alert alert-danger" role="alert">
                            <button class="close" type="button" data-dismiss="alert" aria-label="Close">
                                <span aria-hidden="true">x</span>
                            </button>
                            {{ $errors->first() }}
                        </div>
                    </div>
                </div>
            @endif

            @if(session('success'))
                <div class="row justify-content-center">
                    <div class="col-md-11">
                        <div class="alert alert-success" role="alert">
                            <button class="close" type="button" data-dismiss="alert" aria-label="Close">
                                <span aria-hidden="true">x</span>
                            </button>
                            {{ session()->get('success') }}
                        </div>
                    </div>
                </div>
            @endif

            <div class="row justify-content-center">
                <div class="col-md-8">
                    @include('blog.admin.categories.includes.item_edit_main_col')
                </div>
                <div class="cl-md-3">
                    @include('blog.admin.categories.includes.item_edit_add_col')
                </div>
            </div>
        </div>
    </form>
@endsection

Изменения, которые мы добавили - это код с 9 - 36 строчки.

В этих строках, в зависимости от результата, будет формироваться сообщение об успешном сохранении или о наличии ошибки.

  1. 9 - 11 строки. Прописываем директиву для PHPStorm, чтобы он подсказывал методы для $errors, которые он берет из указанного файла.
  2. 12 - 13 строки. Блок с ошибкой.
  3. 19 строка. Берем только первую ошибку т.к. в нашем случае ошибка может быть только одна - найден/не найден id ресурса.
  4. 25 - 36 строки. Блок с подтверждением.
  5. 32 строка. Через сессию получаем код ответа. Laravel такие коды передает через сессию.

На этом, работа с обновлением категорий закончена.

Примечание. Автор курса отмечает, что большая часть написанного кода - говнокод, который в последующем будет исправляться. Цель такого подхода - понимание того, как стоит писать в Laravel, а как нет!