Как получить сообщения об ошибках из класса FormRequest в Laravel 10 и передать их в контроллер?

Как написать FormRequest в Laravel, чтобы его можно было использовать в двух контроллерах: один контроллер возвращает JSON для работы с API, а другой контроллер возвращает шаблон для работы с пользователем через графический интерфейс? Я хочу обрабатывать результаты FormRequest непосредственно в контроллере. Использую Laravel Framework 10.23.1 и JetStream 3.1.
Изображение к вопросу
  • 16 сентября 2023 г. 6:27
Ответы на вопрос 2
1. Чтобы получить сообщения об ошибках из класса FormRequest в Laravel, вы можете использовать метод `withErrors()` контекста HTTP-ответа. В методе `failedValidation()` в классе FormRequest вы можете переопределить этот метод для формирования ответа с сообщениями об ошибках. Пример:

```php
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\ValidationException;

class MyFormRequest extends FormRequest
{
    protected function failedValidation(Validator $validator)
    {
        if ($this->expectsJson()) {
            throw new HttpResponseException(
                response()->json(['errors' => $validator->errors()], 422)
            );
        }

        throw (new ValidationException($validator))
                    ->errorBag($this->errorBag)
                    ->redirectTo($this->getRedirectUrl());
    }
}
```

В данном примере, если запрос ожидает JSON-ответ, мы выбрасываем исключение HttpResponseException с JSON-ответом, содержащим сообщения об ошибках. В противном случае, мы выбрасываем ValidationException, который будет перехвачен Laravel и будет редирект на страницу с ошибками.

В контроллере вы можете использовать метод `withErrors()` для передачи сообщений об ошибках в представление или сериализации в JSON:

```php
public function store(MyFormRequest $request)
{
    $data = $request->validated();
    
    // Ваша логика обработки данных
    
    if ($request->expectsJson()) {
        return response()->json(['success' => true]);
    }

    return redirect()->back()->with('success', 'Данные успешно сохранены');
}
```

2. Чтобы создать FormRequest, который можно использовать в двух контроллерах, вы можете создать базовый абстрактный класс FormRequest, который наследует класс FormRequest Laravel, и затем создать дочерние классы, которые будут расширять базовый класс.

```php
use Illuminate\Foundation\Http\FormRequest;

abstract class BaseFormRequest extends FormRequest
{
    // Общие правила валидации и методы форматирования данных

    public function response(array $errors)
    {
        if ($this->wantsJson()) {
            return response()->json(['errors' => $errors], 422);
        }

        // Ваш логика для возврата шаблона представления
        // например, используя метод make() и передачу переменных

        return redirect()->back()
            ->withErrors($errors)
            ->withInput();
    }
}
```

```php
class ApiFormRequest extends BaseFormRequest
{
    // Правила валидации для API-запросов
}
```

```php
class WebFormRequest extends BaseFormRequest
{
    // Правила валидации для веб-запросов
}
```

В контроллерах вы можете указать, какой класс формы использовать:

```php
use App\Http\Requests\ApiFormRequest;
use App\Http\Requests\WebFormRequest;

class ApiController extends Controller
{
    public function store(ApiFormRequest $request)
    {
        // Ваша логика для работы с API
    }
}

class WebController extends Controller
{
    public function store(WebFormRequest $request)
    {
        // Ваша логика для работы с веб-интерфейсом
    }
}
```

Таким образом, вы можете использовать один и тот же класс FormRequest с разными контроллерами для обработки разных типов запросов.
Смотрите на заголовки. В Laravel это встроено. Если запрос является AJAX-запросом, возвращаем статус 422 и список ошибок. Если запрос идет из формы, выполняем перенаправление обратно на страницу. Обратите внимание, что для всех запросов к API необходимо использовать формат application/json, чтобы избежать перенаправлений.
Похожие вопросы