Як налаштувати сторінки помилок

Дата оновлення перекладу 2022-12-14

Як налаштувати сторінки помилок

В додатках Symfony всі помилки сприймаються як виключення, незалежно від того, чи є вони простою помилкою 404 "Не знайдено", чи фатальною помилкою через виклик якогось виключення у вашому коді.

В середовиші розробки, Symfony ловить всі виключення і відображає спеціальну сторінку виключень з великою кількістю інформації по налагодженню, щоб допомогти вам швидко знайти основну проблему:

Типова сторінка виключень в середовищі розробки

Так як ці сторінки містять багато чутливої внутрішньої інформації, Symfony не буде відображати її в середовищі виробництва. Замість цього, вона продемонструє просту та загальну помилку сторінка помилки:

Типова сторінка виключень в середовищі виробництва

Сторінки помилок в середовищі виробництва можна налаштувати різними способами, в залежності від ваших потреб:

  1. Якщо ви просто хочете змінити зміст та стилі сторінок помилок так, щоб вони співпадали з рештою вашого додатку, перевизначте шаблони помилок за замовчуванням ;
  2. Якщо ви хочете змінити зміст виведення помилки не в HTML, створіть новий нормалізатор ;
  3. Якщо ви також хочете налаштувати логіку, яку використовує Symfony для генерування ваших сторінок помилок, то перевизначіть контролер помилок за замовчуванням ;
  4. Якщо вам потрібен повний контроль над роботою з виключеннями, виконайте вашу власну логіку - використайте подію kernel.exception .

Перевизначення шаблонів помилок за замовчуванням

Ви можете використовувати вбудований засіб відображення помилок Twig, щоб перевизначати шаблони помилок за замовчуванням. Для цього мають бути встановлені як TwigBundle, так і TwigBridge. Виконайте цю команду, щоб переконатися, що вони встановлені:

1
$ composer require symfony/twig-pack

Коли завантажується сторінка помилки, для відображення шаблону twig та демонастрації користувачу використовується TwigErrorRenderer.

Цей відображувач використовує статус-код HTTP, формат запиту та наступну логіку, щоб визначити ім'я файлу шаблону:

  1. Шукає шаблон для заданого статус-кода (на кшталт error500.html.twig);
  2. Якщо попередній шаблон не існує, відкидає статус-код та шукає загальний шаблон помилок (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.

Окрім цього у вас є доступ до Виключень за допомогою exception, який, наприклад, дозволяє вам виводити відстеження стеку, використовуючи {{ exception.traceAsString }}, або отримати доступ до будь-якого іншого методу об'єкту. Однак будьте обережні, так як це з великою вирогідністю буде оголювати конфіденційну інформацію.

Tip

PHP-помилки також за замовчуванням перетворюються у виключення, тому ви також можете отримати доступ до деталей цих помилок, використовуючи exception.

Безпека та сторінки 404

У зв'язку з порядком, в якому завантажуються маршрутизація та безпека, конфіденційна інформація не буде доступною на ваших сторінках 404. Це означає, що буде здаватися, що ваш користувач не увійшов в систему на сторінці 404 (це буде працювати при тестуванні, але не у виробництві).

Тестування сторінок помилок під час розробки

В той час як ви знаходитесь в середовищі розробки, Symfony відображає велику сторінку виключень замість вашої нової блискучої сторінки помилок. Так як вам побачити, як вона виглядає зсередини, та налагодити її?

На щастя, ExceptionController за замовчуванням дозволяє вам попередній перегляд вашої сторінки помилок під час розробки.

Щоб використати цю функцію, вам необхідно завантажити спеціальні маршрути, надані TwigBundle (якщо застосунок використовує Symfony Flex, то вони завантажуються автоматично при установці підтримки Twig):

  • YAML
  • XML
  • PHP
1
2
3
4
# config/routes/dev/twig.yaml
_errors:
    resource: '@TwigBundle/Resources/config/routing/errors.xml'
    prefix:   /_error

З додаванням цього маршруту, ви можете використовувати такі URL для попереднього перегляду сторінки помилки для заданого статус-коду у вигляді HTML, або для заданого статус-коду та формату (вам може знадобитися замінити http://localhost/ на хостінг, який використовується у ваших локальних налаштуваннях):

  • http://localhost/_error/{statusCode} для HTML
  • http://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 = [])
    {
        return [
            'content' => 'Це мій користувацький нормалізатор проблеми.',
            'exception'=> [
                'message' => $exception->getMessage(),
                'code' => $exception->getStatusCode(),
            ],
        ];
    }

    public function supportsNormalization($data, string $format = null)
    {
        return $data instanceof FlattenException;
    }
}

Перевизначення ExceptionController за замовчуванням

Якщо вам потрібно трошки більше гнучкості окрім простого перевизначення шаблону, то ви можете змінити контролер, що відображає сторінку помилки. Наприклад, вам може бути потрібно передати додаткові змінні в ваш шаблон.

Щоб зробити це, просто створіть новий контролер де завгодно у вашому додатку, та встановіть опцію конфігурації framework.error_controller , щоб вказати на неї:

  • YAML
  • XML
  • PHP
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) та робить дії на кшталт перенаправлення користувачів на сторінку входу, виконує їх вхід в систему тощо.