Валидация данных и вывод ошибок

Валидация проверяет данные пользователя по заданным правилам и автоматически возвращает его к форме с понятными ошибками, если что-то не так.

Суть: метод $request->validate([...]) принимает массив правил вроде required|email|min:8. При нарушении Laravel сам редиректит назад с ошибками и старым вводом.

Никогда не доверяйте данным из формы: пользователь может оставить поля пустыми, ввести буквы вместо цены или прислать некорректный email. Валидация — это барьер, который проверяет ввод до того, как он попадёт в базу. Laravel делает её декларативной: вы описываете правила, а фреймворк сам проверяет данные, формирует сообщения об ошибках и возвращает пользователя к форме.

Самый простой способ — метод validate() прямо в контроллере. Вы передаёте массив, где ключ — имя поля, а значение — список правил через вертикальную черту. Если все правила пройдены, выполнение продолжается; если нет — Laravel автоматически прерывает обработку и редиректит назад.

Валидация в контроллере

<?php
public function store(Request $request)
{
    // если правила нарушены -> авто-редирект назад с ошибками
    $validated = $request->validate([
        'name'  => 'required|string|max:255',
        'email' => 'required|email|unique:users,email',
        'price' => 'required|numeric|min:0',
        'age'   => 'nullable|integer|between:18,99',
    ]);

    // сюда дойдём только с корректными данными
    Product::create($validated);

    return redirect('/products')->with('success', 'Сохранено!');
}

Вывод ошибок в шаблоне

При ошибке Laravel кладёт сообщения в переменную $errors, а старый ввод — в хелпер old(), чтобы пользователь не заполнял форму заново:

<form method="POST" action="/products">
    @csrf
    <input type="text" name="name" value="{{ old('name') }}">
    @error('name')
        <p style="color:red">{{ $message }}</p>
    @enderror

    <button>Сохранить</button>
</form>

{{-- общий список ошибок --}}
@if ($errors->any())
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif

Как работает под капотом

Метод validate() прогоняет каждое поле через свои правила. Если хоть одно нарушено, он бросает исключение ValidationException, которое Laravel перехватывает: он делает редирект на предыдущую страницу, кладёт ошибки в сессию (откуда их берёт $errors) и сохраняет старый ввод (его читает old()). Контроллер при этом дальше не выполняется.

  ПОТОК ВАЛИДАЦИИ
  --------------
  POST /products  ->  validate(rules)
                          |
            +-------------+-------------+
            |                           |
        всё ок                     есть ошибки
            |                           |
      продолжаем код          throw ValidationException
      (Product::create)               |
                              redirect назад
                              + $errors + old()

Смоделируем простой валидатор на Python: правила задаются словарём, ошибки собираются в список.

Попробуй сам ▶

# Мини-валидатор: словарь правил -> список ошибок
def validate(data, rules):
    errors = {}
    for field, checks in rules.items():
        value = data.get(field)
        for check in checks:
            if check == 'required' and not value:
                errors[field] = 'Поле обязательно'
            elif check == 'email' and value and '@' not in value:
                errors[field] = 'Некорректный email'
    return errors

rules = {'name': ['required'], 'email': ['required', 'email']}
print(validate({'name': 'Анна', 'email': 'bad'}, rules))
print(validate({'name': 'Анна', 'email': '[email protected]'}, rules))

Частые ошибки

  • Доверять validate() без вывода ошибок. Без блока @error пользователь не поймёт, что пошло не так.
  • Терять старый ввод. Без old() форма очищается, и пользователь злится.
  • Дублировать правила. Если одни и те же правила в нескольких местах — пора выносить их в Form Request.

Best practices

  • Используйте результат validate() (он возвращает только проверенные поля) для create().
  • Для сложных форм выносите правила в отдельный класс Form Request (следующий урок).
  • Всегда подставляйте old() в поля и показывайте @error рядом с ними.

Итог: валидация декларативно проверяет ввод и автоматически возвращает пользователя к форме с ошибками и старыми данными. Дальше вынесем правила в отдельные классы Form Request для чистоты контроллеров.

Проверьте себя
1. Что произойдёт, если данные не прошли $request->validate()?
AКонтроллер продолжит выполнение
BLaravel автоматически сделает редирект назад с ошибками и старым вводом
CСервер упадёт
DДанные сохранятся всё равно
2. Где в Blade берутся сообщения об ошибках валидации?
AИз объекта Request
BИз переменной $errors (директива @error)
CИз .env
DИз миграции