Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Обработка ошибок

Что-то всегда идёт не так: статья не найдена, доступ запрещён, база недоступна. В Slim на любую такую ситуацию бросают исключение, а посредник ошибок, подключённый в config/middleware.php, превращает его в ответ с нужным кодом состояния.

Исключения HTTP

Для типовых ошибок в Slim есть готовые классы исключений. Одно из них уже используется в ShowPostAction:

// src/Action/ShowPostAction.php
use Slim\Exception\HttpNotFoundException;
 
$post = $this->posts->find((int) $args['id']);
 
if ($post === null) {
    throw new HttpNotFoundException($request, 'Статья не найдена');
}

Откройте /posts/999 — придёт ответ с кодом 404. Первым аргументом исключению передают запрос, вторым, необязательным, — сообщение.

ИсключениеКодКогда бросать
HttpBadRequestException400Запрос составлен неверно
HttpUnauthorizedException401Нужен вход
HttpForbiddenException403Входа недостаточно, доступ запрещён
HttpNotFoundException404Записи или страницы нет
HttpMethodNotAllowedException405Метод не подходит маршруту

Все они лежат в пространстве имён Slim\Exception. Ошибки 404 для несуществующего адреса и 405 для неподходящего метода Slim бросает сам. Любое другое исключение — ошибка в коде или недоступная база — превращается в ответ с кодом 500.

Страница по умолчанию

При APP_DEBUG=true посредник показывает подробности: класс исключения, файл, строку и цепочку вызовов. При false — короткую страницу с названием ошибки. Она работает, но не похожа на остальной сайт.

Свой шаблон ошибки

Создайте отдельный шаблон. Он не наследует макет: обработчик ошибок работает снаружи остальных слоёв, и функции вроде url_for() в этот момент могут быть ещё не подключены.

{# templates/error.twig #}
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="utf-8">
    <title>Ошибка {{ status }}</title>
</head>
<body>
    <h1>{{ status == 404 ? 'Страница не найдена' : 'Что-то пошло не так' }}</h1>
    <p><a href="/">На главную</a></p>
</body>
</html>

Свой обработчик

Метод addErrorMiddleware() возвращает объект посредника. Ему задают функцию, которая будет формировать ответ вместо стандартной:

// config/middleware.php
use Psr\Http\Message\ServerRequestInterface;
use Slim\Exception\HttpException;
use Slim\Views\Twig;
 
$errorMiddleware = $app->addErrorMiddleware($settings['debug'], true, true);
 
if (!$settings['debug']) {
    $errorMiddleware->setDefaultErrorHandler(
        function (ServerRequestInterface $request, Throwable $exception) use ($app) {
            $status = $exception instanceof HttpException ? $exception->getCode() : 500;
 
            $response = $app->getResponseFactory()->createResponse($status);
 
            return $app->getContainer()->get(Twig::class)
                ->render($response, 'error.twig', ['status' => $status]);
        }
    );
}

У исключений HTTP код состояния возвращает getCode(); для всех остальных берётся 500. Свой обработчик включается только вне режима отладки — при разработке подробная страница Slim полезнее.

Поставьте в .env значение APP_DEBUG=false и откройте /posts/999 — появится ваша страница «Страница не найдена».

Частая ошибка

Режим отладки на рабочем сервере показывает посетителю пути к файлам, текст запросов SQL и фрагменты кода. Первый аргумент addErrorMiddleware() на сервере должен быть false, а узнавать об ошибках нужно из журнала — ему посвящён следующий урок. И не выводите в своём шаблоне текст $exception->getMessage() для ошибок 500: в нём бывают внутренние подробности.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.