- Перевизначення шаблонів помилок за замовчуванням
- Приклад шаблону помилки 404
- Тестування сторінок помилок по час розробки
- Перевизначення ExceptionController по промовчати
- Робота з подією kernel.exception
У додатках Symfony всі помилки сприймаються, як виключення, незалежно від того, чи є вони простою помилкою 404 "не знайдено" або фатальною помилкою, запущеної викликом якогось винятку в вашому коді.
В оточенні розробки , Symfony ловить все виключення і висвітлюються спеціальну сторінку винятків з безліччю інформації з налагодження, щоб допомогти вам швидко виявити основну проблему:
Так як ці сторінки містять багато чутливої внутрішньої інформації, Symfony не відображатиме її в оточенні виробництва. Замість цього, вона покаже просту і загальну помилку сторінка помилки:
Сторінки помилок в оточенні виробництва можна налаштувати різними способами, в залежності від ваших потреб:
- Якщо ви просто хочете змінити зміст і стилі сторінок помилок так, щоб вони збігалися з іншим вашим додатком, перевизначите шаблони помилок за замовчуванням ;
- Якщо ви також хочете налаштувати логіку, використовувану Symfony для генерування ваших сторінок помилок, то перевизначите контролер винятків за замовчуванням ;
- Якщо вам потрібен повний контроль над роботою з винятками, виконайте вашу власну логіку - використовуйте подія the kernel.exception .
Перевизначення шаблонів помилок за замовчуванням
Коли завантажується сторінка помилки, для відображення шаблону twig і демонастраціі користувачеві, використовується внутрішній ExceptionController .
Цей контролер використовує статус-код HTTP, формат запиту і наступну логіку, щоб визначити ім'я файлу шаблону:
- Шукайте шаблон для заданого формату і статус-коду (на кшталт error404.json.twig або error500.html.twig);
- Якщо попередній шаблон не існує, відкиньте статус-код і шукайте спільну шаблон для заданого формату (на кшталт error.json.twig або error.xml.twig);
- Якщо не існує жоден з попередніх шаблонів, використовуйте загальний резеврний HTML-шаблон (error.html.twig).
Щоб перевизначити ці шаблони, просто покладайтеся на стандартний метод Symfony для пеоепределенія шаблонів, які живуть всередині пакету: помістіть їх в каталозі templates / bundles / TwigBundle / Exception /.
Типовий проект, який повертає сторінки HTML і JSON, може виглядати так:
templates / └─ bundles / └─ TwigBundle / └─ Exception / ├─ error404.html.twig ├─ error403.html.twig ├─ error.html.twig # Все інші HTML помилки (включаючи 500) ├─ error404.json. twig ├─ error403.json.twig └─ error.json.twig # Все інші JSON помилки (включаючи 500)
Приклад шаблону помилки 404
Щоб перевизначити шаблон помилки 404 для HTML-сторінок, створіть новий шаблон error404.html.twig, що знаходиться в templates / bundles / TwigBundle / Exception /:
{# Templates / bundles / TwigBundle / Exception / error404.html.twig #} {% extends 'base.html.twig'%} {% block body%} <h1> Page not found </ h1> <p> Запрошення сторінка не знайдена. Перевірте помилки в URL або <a href = "{{path ( 'homepage')}}"> поверніться на домашню сраніцу </ a>. </ P> {% endblock%}
Якщо вони вам знадобляться, ExceptionController передає деяку інформацію в шаблон помилок через змінні status_code і status_text, які зберігають HTTP статус-код і повідомлення відповідно.
Tip
Ви можете налаштувати статус-код, реалізувавши HttpExceptionInterface і його обов'язковий метод getStatusCode (). У зворотному випадку, status_code за замовчуванням будет``500``.
Note
Сторінки винятків, які відображаються в оточенні розробки, можна налаштувати таким же чином, як сторінки про помилки. Створіть новий шаблон exception.html.twig для сторінки стандартного HTML-ісключнія, або exception.json.twig для сторінки JSON-виключення.
Тестування сторінок помилок по час розробки
У той час, як ви перебуваєте в оточенні розробки, Symfony відображає велику сторінку винятків замість вашої нової блискучої сторінки помилок. Так як вам побачити, як вона виглядає зсередини і налагодити її?
На щастя, ExceptionController за замовчуванням дозволяє вам попередній вашої сторінки помилки під час розробки.
Щоб скористатися цією функцією, вам завантажити спеціальні маршрути, надані TwigBundle (якщо додаток використовує Symfony Flex , То вони завантажуються автоматично при установці підтримки Twig):
- YAML # config / routes / dev / twig.yaml _errors resource '@ TwigBundle / Resources / config / routing / errors.xml' prefix / _error
- XML <! - config / routes / dev / twig.xml -> <? Xml version = "1.0" encoding = "UTF-8"?> <Routes xmlns = "http://symfony.com/schema/routing "xmlns: xsi =" http://www.w3.org/2001/XMLSchema-instance "xsi: schemaLocation =" http://symfony.com/schema/routing http://symfony.com/schema/routing/ routing-1.0.xsd "> <import resource =" @ TwigBundle / Resources / config / routing / errors.xml "prefix =" / _error "/> </ routes>
- PHP // config / routes / dev / twig.php use Symfony \ Component \ Routing \ RouteCollection; $ Collection = new RouteCollection (); $ Collection -> addCollection ($ loader -> import ( '@ TwigBundle / Resources / config / routing / errors.xml')); $ Collection -> addPrefix ( "/ _error"); return $ collection;
C додаванням цього маршруту, ви можете використовувати такі URL для попереднього перегляду сторінки помилки для заданого статус-коду у вигляді HTML або для заданого статус-коду і формату.
http: //localhost/index.php/_error/ {statusCode} http: //localhost/index.php/_error/ {statusCode}. {format}
Перевизначення ExceptionController по промовчати
Якщо вам потрібно трохи більше гнучкості крім простого перевизначення шаблону, то ви можете змінити контролер, що відображає странцу помилки. Наприклад, вам може бути нужо передати додаткові змінні в ваш шаблон.
Щоб зробити це, просто створіть новий контролер де завгодно в вашому додатку, і встановіть опцію конфігурації twig.exception_controller , Щоб вказати на неї:
- YAML # config / packages / twig.yaml twig exception_controller App \ Controller \ ExceptionController :: showException
- XML 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <! - config / packages / twig.xml -> <? Xml version = "1.0" encoding = "UTF-8"?> <Container xmlns = "http://symfony.com/schema/dic/services" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: twig = "http://symfony.com/ schema / dic / twig "xsi: schemaLocation =" http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com / schema / dic / twig http://symfony.com/schema/dic/twig/twig-1.0.xsd "> <twig: config> <twig: exception-controller> App \ Controller \ ExceptionController :: showException </ twig : exception-controller> </ twig: config> </ container>
- PHP // config / packages / twig.php $ container -> loadFromExtension ( 'twig', array ( 'exception_controller' => 'App \ Controller \ ExceptionController :: showException', // ...));
клас ExceptionListener , Який використовується TwigBundle в якості слухача події kernel.exception, створює запит, який буде розгорнуто в вашому контролері. На додаток, вашому контролеру будуть передані два параметри:
exception Сутність FlattenException , Створення їх оброблюваного виключення. logger Сутність DebugLoggerInterface , Яка може в деяких випадках бути null.
Замість створення новго контролера винятків з нуля, ви звичайно ж можете також розширити клас за замовчуванням ExceptionController . В такому случасе, ви можете захотіти перевизначити один або обидва методи showAction () і findTemplate (). Останній містить шаблон для використання.
Note
У разі розширення класу ExceptionController , Ви можете конфігурувати севіс, щоб передати оточенню Twig і конструктору прапора debug.
- YAML # config / services.yaml services _defaults # ... be sure autowiring is enabled autowire true # ... App \ Controller \ CustomExceptionController public true arguments $ debug '% kernel.debug%'
- XML 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <! - config / services.xml -> <? Xml version = "1.0" encoding = "UTF-8"?> <Container xmlns = "http://symfony.com/schema/dic/services" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: schemaLocation = "http://symfony.com / schema / dic / services http://symfony.com/schema/dic/services/services-1.0.xsd "> <services> <! - ... be sure autowiring is enabled -> <defaults autowire =" true "/> <! - ... -> <service id =" App \ Controller \ CustomExceptionController "public =" true "> <argument key =" $ debug ">% kernel.debug% </ argument> < / service> </ services> </ container>
- PHP // config / services.php use App \ Controller \ CustomExceptionController; $ Container -> autowire (CustomExceptionController :: class) -> setArgument ( '$ debug', '% kernel.debug%');
Робота з подією kernel.exception
коли викликається виняток, клас HttpKernel ловить його і розгортає подія kernel.exception. Це дає вам можливість конвертувати виключення в Response декількома різними способами.
Робота з цією подією насправді значно потужніший, ніж пояснювалося раніше, але також вимагає ретельного розуміння внутрішніх процесів Symfony. Уявіть, що ваш код викликає спеціальні виключення з конкретним значенням у вашому домені додатку.
Написання вашого власного слухача подій для події kernel.exception дозволяє вам ближче рассмотретьісключеніе і виконати стосовно нього різні дії. Ці дії можуть включати в себе запис логу виключення, перенаправлення користувача на іншу сторінку або вiдтворення спеціальних сторінок помилки.
Note
Якщо ваш слухач викликає setResponse () в подію GetResponseForExceptionEvent , Поширення буде зупинено і клієнтові буде відправлений відповідь.
Цей підхід дозволяє вам створювати централізовану і багатошарову обробку помилок: замість того, щоб ловити (і обробляти) одні й ті ж виключення в різних контролерах знову і знову, ви просто можете мати одного (або кількох) слухачів, щоб розбиратися з ними.
Tip
Дивіться код класу ExceptionListener для реального прикладу просунутого слухача такого типу. Цей слухач обробляє різні винятки, пов'язані з безпекою, які викликаються в вашому додатку (як AccessDeniedException ) І вживає заходів на кшталт перенаправлення користувачів на сторінку входу, виконує їх вхід в систему і ін.
Так як вам побачити, як вона виглядає зсередини і налагодити її?Xml -> <?
Encoding = "UTF-8"?
Xml -> <?
Encoding = "UTF-8"?
Xml -> <?
Encoding = "UTF-8"?