Як налаштувати сторінки помилок
Дата оновлення перекладу 2024-05-13
Як налаштувати сторінки помилок
В додатках Symfony всі помилки сприймаються як виключення, незалежно від того, чи є вони простою помилкою 404 "Не знайдено", чи фатальною помилкою через виклик якогось виключення у вашому коді.
В середовиші розробки, Symfony ловить всі виключення і відображає спеціальну сторінку виключень з великою кількістю інформації по налагодженню, щоб допомогти вам швидко знайти основну проблему:
Так як ці сторінки містять багато чутливої внутрішньої інформації, Symfony не буде відображати її в середовищі виробництва. Замість цього, вона продемонструє просту та загальну помилку сторінка помилки:
Сторінки помилок в середовищі виробництва можна налаштувати різними способами, в залежності від ваших потреб:
- Якщо ви просто хочете змінити зміст та стилі сторінок помилок так, щоб вони співпадали з рештою вашого додатку, перевизначте шаблони помилок за замовчуванням ;
- Якщо ви хочете змінити зміст виведення помилки не в HTML, створіть новий нормалізатор ;
- Якщо ви також хочете налаштувати логіку, яку використовує Symfony для генерування ваших сторінок помилок, то перевизначіть контролер помилок за замовчуванням ;
- Якщо вам потрібен повний контроль над роботою з виключеннями, виконайте вашу власну логіку - використайте подію kernel.exception .
Перевизначення шаблонів помилок за замовчуванням
Ви можете використовувати вбудований засіб відображення помилок Twig, щоб перевизначати шаблони помилок за замовчуванням. Для цього мають бути встановлені як TwigBundle, так і TwigBridge. Виконайте цю команду, щоб переконатися, що вони встановлені:
1
$ composer require symfony/twig-pack
Коли завантажується сторінка помилки, для відображення шаблону twig та демонастрації користувачу використовується TwigErrorRenderer.
Цей відображувач використовує статус-код HTTP, формат запиту та наступну логіку, щоб визначити ім'я файлу шаблону:
- Шукає шаблон для заданого статус-кода (на кшталт
error500.html.twig
); - Якщо попередній шаблон не існує, відкидає статус-код та шукає загальний
шаблон помилок (
error.html.twig
).
Щоб перевизначити ці шаблони, просто покладіться на стандартний метод Symfony для
перевизначення шаблонів, що живуть всередині пакету:
розмістить їх в каталозі templates/bundles/TwigBundle/Exception/
.
Типовий проект, який повертає сторінки HTML та JSON, може виглядати так:
1 2 3 4 5 6 7
templates/
└─ bundles/
└─ TwigBundle/
└─ Exception/
├─ error404.html.twig
├─ error403.html.twig
└─ error.html.twig # Всі інші JSON помилки (включно з 500)
Приклад шаблону помилки 404
Щоб перевизначити шаблон помилки 404 для HTML-сторінки, створіть новий шаблон
error404.html.twig
, який знаходиться в templates/bundles/TwigBundle/Exception/
:
1 2 3 4 5 6 7 8 9 10 11
{# templates/bundles/TwigBundle/Exception/error404.html.twig #}
{% extends 'base.html.twig' %}
{% block body %}
<h1>Сторінка не знайдена</h1>
<p>
Запитувана сторінка не знайдена. Перевірте помилки в URL або
<a href="{{ path('homepage') }}">поверніться на домашню сторінку</a>.
</p>
{% endblock %}
Якщо вони вам знадобляться, TwigErrorRenderer
передає деяку інформацію в шаблон
помилок через змінні status_code
та status_text
, які зберігають HTTP статус-код
та повідомлення, відповідно.
Tip
Ви можете налаштувати статус-код, реалізуваши
HttpExceptionInterface
та його обов'язковий метод getStatusCode()
. В іншому випадку, status_code
за замовчуванням буде 500
.
Додатково ви маєте доступ до об'єкта HttpException
через змінну Twig exception
. Наприклад, якщо виключення встановлює повідомлення
(наприклад, за допомогою throw $this->createNotFoundException('The product does not exist')
),
використовуйте {{ exception.message }}
для виведення цього повідомлення. Ви також можете вивести
трасування стеку за допомогою {{ exception.traceAsString }}
, але не робіть цього для кінцевих
користувачів, оскільки трасування містить конфіденційні дані.
Tip
PHP-помилки також за замовчуванням перетворюються у виключення, тому ви
також можете отримати доступ до деталей цих помилок, використовуючи exception
.
Безпека та сторінки 404
У зв'язку з порядком, в якому завантажуються маршрутизація та безпека, конфіденційна інформація не буде доступною на ваших сторінках 404. Це означає, що буде здаватися, що ваш користувач не увійшов в систему на сторінці 404 (це буде працювати при тестуванні, але не у виробництві).
Тестування сторінок помилок під час розробки
В той час як ви знаходитесь в середовищі розробки, Symfony відображає велику сторінку виключень замість вашої нової блискучої сторінки помилок. Так як вам побачити, як вона виглядає зсередини, та налагодити її?
На щастя, ExceptionController
за замовчуванням дозволяє вам попередній
перегляд вашої сторінки помилок під час розробки.
Щоб використати цю функцію, вам необхідно завантажити спеціальні маршрути, надані TwigBundle (якщо застосунок використовує Symfony Flex, то вони завантажуються автоматично при установці підтримки Twig):
1 2 3 4 5
# config/routes/framework.yaml
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error
З додаванням цього маршруту, ви можете використовувати такі URL для попереднього перегляду
сторінки помилки для заданого статус-коду у вигляді HTML, або для заданого статус-коду та
формату (вам може знадобитися замінити http://localhost/
на хостінг, який використовується
у ваших локальних налаштуваннях):
http://localhost/_error/{statusCode}
для HTMLhttp://localhost/_error/{statusCode}.{format}
для будь-якого іншого формату
Перевизначення виведення помилок для не-HTML форматів
Щоб перевизначити не-HTML виведення помилки, необхідно встановити компонент Serializer.
1
$ composer require symfony/serializer-pack
Компонент Serializer має вбудований нормалізатор FlattenException
(ProblemNormalizer) та кодувальники
JSON/XML/CSV/YAML. Коли ваш застосунок викличе виключення, Symfony може вивести його в один
з цих форматів. Якщо ви хочете змінити зміст виведення, створіть Нормалізатор, який
підтримує введення FlattenException
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# src/Serializer/MyCustomProblemNormalizer.php
namespace App\Serializer;
use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class MyCustomProblemNormalizer implements NormalizerInterface
{
public function normalize($exception, string $format = null, array $context = []): array
{
return [
'content' => 'This is my custom problem normalizer.',
'exception'=> [
'message' => $exception->getMessage(),
'code' => $exception->getStatusCode(),
],
];
}
public function supportsNormalization($data, string $format = null, array $context = []): bool
{
return $data instanceof FlattenException;
}
}
Перевизначення ExceptionController за замовчуванням
Якщо вам потрібно трошки більше гнучкості окрім простого перевизначення шаблону, то ви можете змінити контролер, що відображає сторінку помилки. Наприклад, вам може бути потрібно передати додаткові змінні в ваш шаблон.
Щоб зробити це, просто створіть новий контролер де завгодно у вашому додатку, та встановіть опцію конфігурації framework.error_controller , щоб вказати на неї:
1 2 3
# config/packages/framework.yaml
framework:
error_controller: App\Controller\ErrorController::show
Клас ExceptionListener,
який використовується TwigBundle в якості слухача події kernel.exception
, створює
запит, який буде розгорнуто у вашому контролері. На додаток, вашому контролеру будуть
передані два параметри:
exception
- Обробка початкового екземпляру Throwable.
logger
-
Екземпляр DebugLoggerInterface,
який може в деяких випадках бути
null
.
Tip
Попередній перегляд сторінки помилки також працює з вашими власними контролерами, налаштованими як завгодно.
Робота з подією kernel.exception
Коли викликається виключення, клас HttpKernel
ловить його та оголошує подію kernel.exception
. Це надає вам можливість конвертувати
виключення в Response
декількома різними способами.
Робота з цією подією насправді набагато потужніша, ніж пояснювалося раніше, але також потребує ретельного розуміння внутрішніх процесів Symfony. Уявіть, що вам код викликає спеціальні виключення з конкретним значенням у вашому домені додатку.
Написання вашого власного слухача подій для події
kernel.exception
дозволяє вам ближче розглянути виключення та зробити по
відношенню до нього різні дії. Ці дії можуть включати в себе запис логу виключення,
перенаправлення користувача на іншу сторінку або вдіображення спеціальних сторінок
помилки.
Note
Якщо ваш слухач викликає setThrowable()
в події
ExceptionEvent,
розповсюдження буде зупинено і клієнту буде надіслано відповідь.
Цей підхід дозволяє вам створювати централізовану та багатошарову обробку помилок: замість того, щоб ловити (та обробляти) одні й ті самі виключення в різних контролерах знову і знову, ви просто можете мати одного (або декілька) слухачів, щоб розбиратися з ними.
Tip
Дивіться код класу ExceptionListener для реального прикладу просунутого слухача такого типу. Цей слухач обробляє різноманітні виключення, пов'язані з безпекою, які викликаються у вашому додатку (як AccessDeniedException) та робить дії на кшталт перенаправлення користувачів на сторінку входу, виконує їх вхід в систему тощо.