Laravel: куда бросать исключения HTTP

Фон

В приложениях PHP / Laravel MVC коды ответов и тела часто определяются созданным исключением. Если выдается исключение HTTP (наследование от Symfony\Component\HttpKernel\Exception\HttpException) выдаются правильные коды ответов (и в некоторых случаях ответы JSON). Существуют и другие типы исключений, которые также не связаны с http и могут быть выброшены.

Вопрос

Где следует генерировать исключения HTTP?

  • Только контроллер
  • В В любом месте. Глубокий или неглубокий в стеке приложений.

Должен ли я перехватывать свои исключения в контроллере и выдавать HTTP-версии этих исключений? Или я должен просто выбросить исключение HTTP где-нибудь глубоко внутри класса обслуживания, репозитория или утилиты, учитывая, что 99% приложений инфраструктуры MVC в любом случае основаны на жизненном цикле запроса HTTP >> ответа?

3

Решение

Мой ответ не нацелен на Laravel, так как я считаю, что работа с базовым мышлением идет вразрез с вашим первоначальным вопросом.

Всегда выбрасывайте специальное исключение а затем обработать преобразование в контроллере. В этом случае заверните его в HttpException, Для этого есть несколько веских причин:

  • Решение о том, какой код статуса и сообщение делегируются реализации (в данном случае интеграция с вашей платформой). Это означает, что вы можете оставить свой код в любой среде и обрабатывать ошибки отдельно.
  • Вы решили, что вам нужна команда / работник CLI, и теперь ваш HttpException броски в вашем сервисе не имеют смысла для вашей команды CLI.

По сути, думая о калькуляторе, он бросил бы DivisionByZeroException, Для контроллера вы бы обернули это в HttpException 400 BAD REQUEST и перебросить. Для CLI ваша команда может просто позволить отображать исключение на экране Division By Zero, В любом случае это решение не принимается вашей службой.

4

Другие решения

Где следует генерировать исключения HTTP?

Хотя это, как правило, зависит от предпочтений, сама структура, по-видимому, заняла по этому поводу самоуверенную позицию, и вы должны бросать их куда угодно. На самом деле у Laravel есть несколько полезных помощников, которые упрощают создание исключений с соответствующими кодами ответов:

abort(403, "Exception message"); //Will throw an HTTP exception with code 403
abort_if(true, 400, "Condition failed"); //Will throw a 400 error if the first parameter is true
abort_unless(false, 422, "Condition failed"); //Will throw a 422 error if the first parameter is false

Практический пример:

 public function getById($id) {
$model = Model::find($id);
//These are equivalent
if ($model == null) {
abort(404, "$id not found");
}
abort_if($model == null, 404, "$id not found");
abort_unless($model != null, 404, "$id not found");
}

Это затронуто в Раздел обработки ошибок руководства

Обратите внимание, что abort действительно вызывает исключения HTTP, так что вы все равно можете их перехватить и обработать, если вам нужно.

Похоже, существует общее недоразумение по этому вопросу. Насколько я понимаю, вопрос заключался в том, где следует генерировать исключения HTTP, но он переходит к более общей обработке исключений в контексте HTTP.

Прежде всего, если у вас есть исключение HTTP, то есть исключение, которое имеет смысл только в контексте цикла HTTP-запроса / ответа, вы должны быть в состоянии выбросить его там, где оно происходит, и не выбрасывать что-то другое с целью преобразования это когда он достигает контроллера, это то, что abort помощники там делать.

Однако, если у вас есть исключение (любое исключение), которое следует интерпретировать с помощью специального кода ответа http, если оставить его необработанным, у вас есть варианты с этим справиться:

  1. Сделать это исключение наследовать от Symfony HttpException (Это может показаться немного странным, что совершенно нормальное исключение наследуется от класса, который не имеет смысла вне жизненного цикла запроса / ответа).
  2. Реализовать render метод в вашем исключении например.:

    class SpecialException extends Exception {
    public function render() {
    return response()->view('errors.403', [], 403);
    }
    }
    
  3. Имейте определенное поведение обработки в вашем \ App \ Exceptions \ Handler, например:

    class Handler {
    // ....
    public function render($request, $exception) {
    if ($exception instanceof SpecialException) {
    return response()->view('errors.403', [], 403);
    }
    return parent::render()
    }
    }
    
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector