Інколи дані треба нормалізувати до валідації: прибрати пробіли з телефону, згенерувати 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]).