Обработка исключений
Конфигурация
config/exception.php
return [
// Здесь конфигурируется класс обработки исключений
'' => support\exception\Handler::class,
];
В режиме нескольких приложений вы можете отдельно настроить класс обработки исключений для каждого приложения, см. Многоприложение
Класс по умолчанию для обработки исключений
В Webman исключения по умолчанию обрабатываются классом support\exception\Handler
. Вы можете изменить класс по умолчанию, отредактировав файл конфигурации config/exception.php
. Класс обработки исключений должен реализовывать интерфейс Webman\Exception\ExceptionHandlerInterface
.
interface ExceptionHandlerInterface
{
/**
* Записывает лог
* @param Throwable $e
* @return mixed
*/
public function report(Throwable $e);
/**
* Отображает ответ
* @param Request $request
* @param Throwable $e
* @return Response
*/
public function render(Request $request, Throwable $e) : Response;
}
Отображение ответа
Метод render
в классе обработки исключений используется для отображения ответа.
Если значение debug
в файле конфигурации config/app.php
равно true
(в дальнейшем будет обозначаться как app.debug=true
), будет возвращена подробная информация об исключении, в противном случае будет возвращена краткая информация об исключении.
Если запрос ожидает JSON-ответ, то информация об исключении будет возвращена в формате JSON, например:
{
"code": "500",
"msg": "Информация об исключении"
}
Если app.debug=true
, в JSON-данные будет добавлено дополнительное поле trace
, содержащие подробный стек вызовов.
Вы можете написать свой собственный класс обработки исключений, чтобы изменить логику обработки исключений по умолчанию.
Бизнес-исключение BusinessException
Иногда мы хотим прервать запрос в определенной вложенной функции и вернуть сообщение об ошибке клиенту, для этого можно выбросить BusinessException
.
Например:
<?php
namespace app\controller;
use support\Request;
use support\exception\BusinessException;
class FooController
{
public function index(Request $request)
{
$this->chackInpout($request->post());
return response('hello index');
}
protected function chackInpout($input)
{
if (!isset($input['token'])) {
throw new BusinessException('Ошибка параметра', 3000);
}
}
}
В приведенном примере будет возвращено:
{"code": 3000, "msg": "Ошибка параметра"}
Внимание
Бизнес-исключение BusinessException не требует обработки через try, так как фреймворк автоматически перехватывает его и возвращает соответствующий вывод в зависимости от типа запроса.
Пользовательское бизнес-исключение
Если приведенный выше ответ не соответствует вашим требованиям, например, если вы хотите изменить msg
на message
, вы можете создать пользовательское исключение MyBusinessException
.
Создайте app/exception/MyBusinessException.php
со следующим содержимым:
<?php
namespace app\exception;
use support\exception\BusinessException;
use Webman\Http\Request;
use Webman\Http\Response;
class MyBusinessException extends BusinessException
{
public function render(Request $request): ?Response
{
// Если запрос в формате json, возвращаем json-данные
if ($request->expectsJson()) {
return json(['code' => $this->getCode() ?: 500, 'message' => $this->getMessage()]);
}
// Если запрос не в формате json, возвращаем страницу
return new Response(200, [], $this->getMessage());
}
}
Таким образом, когда бизнес-логика вызывает
use app\exception\MyBusinessException;
throw new MyBusinessException('Ошибка параметра', 3000);
Запрос в формате JSON получит аналогичный ответ в формате JSON:
{"code": 3000, "message": "Ошибка параметра"}
Подсказка
Поскольку исключение BusinessException относится к бизнес-исключениям (например, ошибка ввода параметров пользователем), оно предсказуемо, и фреймворк не считает его фатальной ошибкой и не записывает в лог.
Резюме
В любых случаях, когда вы хотите прервать текущий запрос и вернуть информацию клиенту, можно рассмотреть использование исключения BusinessException
.