Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як змінити вхідні дані перед валідацією: merge, prepareForValidation і чому з цим варто бути обережним?

Інколи дані треба нормалізувати до валідації: прибрати пробіли з телефону, згенерувати slug з назви, привести email до нижнього регістру.

merge і mergeIfMissing:

$request->merge(['slug' => Str::slug($request->input('title'))]);
$request->mergeIfMissing(['locale' => 'uk']);   // лише якщо поля немає

У Form Request - prepareForValidation():

final class StorePostRequest extends FormRequest
{
    protected function prepareForValidation(): void
    {
        $this->merge([
            'slug' => Str::slug($this->input('slug') ?: $this->input('title')),
            'phone' => preg_replace('/\D+/', '', (string) $this->input('phone')),
        ]);
    }

    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:255'],
            'slug' => ['required', 'alpha_dash', Rule::unique('posts')],
            'phone' => ['nullable', 'digits_between:10,12'],
        ];
    }
}

Правила перевіряють уже нормалізоване значення: унікальність slug перевіряється для того slug, який справді буде збережено.

Після валідації - passedValidation() - для перетворень, які не мають впливати на перевірку (наприклад, хешування).

Глобальна нормалізація вже є: middleware TrimStrings обрізає пробіли, а ConvertEmptyStringsToNull перетворює порожні рядки на null. Через це nullable правила й порожні поля працюють очікувано. Виключити поля (наприклад, пароль) можна в bootstrap/app.php.

Чому обережно:

  • merge змінює спільний об'єкт запиту. Після нього змінене значення бачать усі: middleware, що виконуються далі, слухачі, логування. Нормалізація в одному контролері раптово впливає на інший код;
  • логіка ховається: читач контролера не бачить, що phone уже не те, що надіслав клієнт;
  • не підміняйте значення, які мають бути помилкою. Якщо status невідомий, правильна відповідь - помилка валідації, а не тихе merge(['status' => 'draft']);
  • не додавайте через merge дані, що не повинні приходити від клієнта (user_id, роль), щоб «пройти валідацію». Такі поля встановлюються явно при збереженні, а не потрапляють у вхідні дані.

Альтернатива для обчислюваних полів: не змінювати запит, а додати значення при збереженні: Post::create([...$request->validated(), 'user_id' => $request->user()->id]).

Докладніше в документації: Додавання вхідних даних

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання