Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Классы запросов

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

Создание

php artisan make:request StorePostRequest

Класс появится в app/Http/Requests.

Правила

Правила возвращает метод rules(). Их удобно записывать массивами:

namespace App\Http\Requests;
 
use Illuminate\Foundation\Http\FormRequest;
 
class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }
 
    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
            'category_id' => ['required', 'exists:categories,id'],
            'tags' => ['array'],
            'tags.*' => ['integer', 'exists:tags,id'],
        ];
    }
}

Правило exists проверяет, что такая запись есть в таблице. Запись tags.* задаёт правила для каждого элемента массива.

Использование в контроллере

Достаточно указать класс в типе параметра. Проверка выполнится до входа в метод:

public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());
 
    return redirect()->route('posts.show', $post);
}

validated() возвращает только те поля, для которых заданы правила. Лишние данные из запроса в базу не попадут.

Проверка прав

Метод authorize() решает, можно ли вообще выполнять запрос. Если он вернёт false, пользователь получит ошибку 403:

public function authorize(): bool
{
    return $this->user()->can('update', $this->route('post'));
}

Свои сообщения

public function messages(): array
{
    return [
        'title.required' => 'Укажите заголовок статьи.',
        'title.max' => 'Заголовок не длиннее 255 символов.',
    ];
}
 
public function attributes(): array
{
    return [
        'category_id' => 'категория',
    ];
}

attributes() заменяет в стандартных сообщениях имя поля на понятное название.

Подготовка данных

prepareForValidation() выполняется до проверки — в нём приводят данные к нужному виду:

use Illuminate\Support\Str;
 
protected function prepareForValidation(): void
{
    $this->merge([
        'slug' => Str::slug($this->title),
        'is_published' => $this->boolean('is_published'),
    ]);
}

Правила, зависящие от записи

При редактировании уникальность нужно проверять, исключая саму запись:

use Illuminate\Validation\Rule;
 
public function rules(): array
{
    return [
        'slug' => ['required', Rule::unique('posts')->ignore($this->route('post'))],
        'status' => ['required', Rule::in(['draft', 'published'])],
    ];
}

Частая ошибка

Метод $request->all() возвращает всё, что прислал пользователь, включая поля, которых нет в правилах. Передав его в create(), вы позволите подставить лишнее поле — например, is_admin. Берите данные только из validated().

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.