How to Customize Error Pages

In Symfony applications, all errors are treated as exceptions, no matter if they are a 404 Not Found error or a fatal error triggered by throwing some exception in your code.

Symfony アプリケーションでは、エラーが 404 Not Found エラーであるか、コードで例外をスローすることによって引き起こされる致命的なエラーであるかに関係なく、すべてのエラーが例外として扱われます。

In the development environment, Symfony catches all the exceptions and displays a special exception page with lots of debug information to help you discover the root problem:

開発環境では、Symfony はすべての例外をキャッチし、根本的な問題を発見するのに役立つ多くのデバッグ情報を含む特別な例外ページを表示します:
A typical exception page in the development environment

Since these pages contain a lot of sensitive internal information, Symfony won't display them in the production environment. Instead, it'll show a minimal and generic error page:

これらのページには多くの機密内部情報が含まれているため、Symfony は本番環境ではそれらを表示しません。代わりに、最小限の一般的なエラー ページが表示されます。
A typical error page in the production environment

Error pages for the production environment can be customized in different ways depending on your needs:

本番環境のエラー ページは、ニーズに応じてさまざまな方法でカスタマイズできます。
  1. If you only want to change the contents and styles of the error pages to match the rest of your application, override the default error templates;
    エラー ページの内容とスタイルをアプリケーションの残りの部分に合わせて変更するだけの場合は、デフォルトのエラー テンプレートをオーバーライドします。
  2. If you want to change the contents of non-HTML error output, create a new normalizer;
    HTML 以外のエラー出力の内容を変更する場合は、新しいノーマライザーを作成します。
  3. If you also want to tweak the logic used by Symfony to generate error pages, override the default error controller;
    Symfony がエラー ページを生成するために使用するロジックを微調整したい場合は、デフォルトのエラー コントローラーをオーバーライドします。
  4. If you need total control of exception handling to run your own logic use the kernel.exception event.
    独自のロジックを実行するために例外処理を完全に制御する必要がある場合は、kernel.exception イベントを使用します。

Overriding the Default Error Templates

You can use the built-in Twig error renderer to override the default error templates. Both the TwigBundle and TwigBridge need to be installed for this. Run this command to ensure both are installed:

組み込みの Twig エラー レンダラーを使用して、デフォルトのエラー テンプレートをオーバーライドできます。これには、TwigBundle と TwigBridge の両方をインストールする必要があります。次のコマンドを実行して、両方がインストールされていることを確認します。
1
$ composer require symfony/twig-pack

When the error page loads, TwigErrorRenderer is used to render a Twig template to show the user.

エラー ページが読み込まれると、TwigErrorRendereris を使用して Twig テンプレートをレンダリングし、ユーザーに表示します。

This renderer uses the HTTP status code and the following logic to determine the template filename:

このレンダラーは、HTTP ステータス コードと次のロジックを使用して、テンプレート ファイル名を決定します。
  1. Look for a template for the given status code (like error500.html.twig);
    指定されたステータス コード (error500.html.twig など) のテンプレートを探します。
  2. If the previous template doesn't exist, discard the status code and look for a generic error template (error.html.twig).
    前のテンプレートが存在しない場合は、ステータス コードを破棄し、一般的なエラー テンプレート (error.html.twig) を探します。

To override these templates, rely on the standard Symfony method for overriding templates that live inside a bundle and put them in the templates/bundles/TwigBundle/Exception/ directory.

これらのテンプレートをオーバーライドするには、バンドル内に存在するテンプレートをオーバーライドするための標準の Symfony メソッドに依存し、それらを templates/bundles/TwigBundle/Exception/ ディレクトリに配置します。

A typical project that returns HTML pages might look like this:

HTML ページを返す典型的なプロジェクトは次のようになります。
1
2
3
4
5
6
7
templates/
└─ bundles/
   └─ TwigBundle/
      └─ Exception/
         ├─ error404.html.twig
         ├─ error403.html.twig
         └─ error.html.twig      # All other HTML errors (including 500)

Example 404 Error Template

To override the 404 error template for HTML pages, create a new error404.html.twig template located at templates/bundles/TwigBundle/Exception/:

HTML ページの 404 エラー テンプレートをオーバーライドするには、templates/bundles/TwigBundle/Exception/ にある newerror404.html.twig テンプレートを作成します。
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>Page not found</h1>

    <p>
        The requested page couldn't be located. Checkout for any URL
        misspelling or <a href="{{ path('homepage') }}">return to the homepage</a>.
    </p>
{% endblock %}

In case you need them, the TwigErrorRenderer passes some information to the error template via the status_code and status_text variables that store the HTTP status code and message respectively.

それらが必要な場合、TwigErrorRenderer は、HTTP ステータス コードとメッセージをそれぞれ格納する status_code 変数と status_text 変数を介して、いくつかの情報をエラー テンプレートに渡します。

Tip

ヒント

You can customize the status code of an exception by implementing HttpExceptionInterface and its required getStatusCode() method. Otherwise, the status_code will default to 500.

HttpExceptionInterface とそれに必要な getStatusCode() メソッドを実装することで、例外のステータス コードをカスタマイズできます。それ以外の場合、status_code はデフォルトで 500 になります。

Additionally you have access to the Exception with exception, which for example allows you to output the stack trace using {{ exception.traceAsString }} or access any other method on the object. You should be careful with this though, as this is very likely to expose sensitive data.

さらに、例外を伴う例外にアクセスできます。これにより、たとえば、{{ exception.traceAsString }} を使用してスタック トレースを出力したり、オブジェクトの他のメソッドにアクセスしたりできます。ただし、機密データが公開される可能性が非常に高いため、これには注意が必要です。

Tip

ヒント

PHP errors are turned into exceptions as well by default, so you can also access these error details using exception.

PHP エラーもデフォルトで例外に変換されるため、例外を使用してこれらのエラーの詳細にアクセスすることもできます。

Security & 404 Pages

Due to the order of how routing and security are loaded, security information will not be available on your 404 pages. This means that it will appear as if your user is logged out on the 404 page (it will work while testing, but not on production).

ルーティングとセキュリティが読み込まれる順序が原因で、404 ページでセキュリティ情報を利用することはできません。これは、youruser が 404 ページでログアウトしたかのように表示されることを意味します (テスト中は機能しますが、本番環境では機能しません)。

Testing Error Pages during Development

While you're in the development environment, Symfony shows the big exception page instead of your shiny new customized error page. So, how can you see what it looks like and debug it?

開発環境にいる間、Symfony は光沢のある新しいカスタマイズされたエラー ページの代わりに大きな例外ページを表示します。では、どのように見えるかを確認してデバッグするにはどうすればよいでしょうか。

Fortunately, the default ErrorController allows you to preview your error pages during development.

幸いなことに、デフォルトの ErrorController を使用すると、開発中にエラー ページをプレビューできます。

To use this feature, you need to load some special routes provided by FrameworkBundle (if the application uses Symfony Flex they are loaded automatically when installing symfony/framework-bundle):

この機能を使用するには、FrameworkBundle が提供するいくつかの特別なルートをロードする必要があります (アプリケーションが Symfony Flex を使用している場合、それらは symfony/framework-bundle のインストール時に自動的にロードされます):
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
# config/routes/framework.yaml
when@dev:
    _errors:
        resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
        prefix:   /_error

With this route added, you can use URLs like these to preview the error page for a given status code as HTML or for a given status code and format (you might need to replace http://localhost/ by the host used in your local setup):

このルートを追加すると、これらのような URL を使用して、HTML としての特定のステータス コード、または特定のステータス コードと形式のエラー ページをプレビューできます (http://localhost/ をローカル セットアップで使用されているホストに置き換える必要がある場合があります)。 :
  • http://localhost/_error/{statusCode} for HTML
    HTML の場合は http://localhost/_error/{statusCode}
  • http://localhost/_error/{statusCode}.{format} for any other format
    http://localhost/_error/{statusCode}.{format} その他の形式の場合

Overriding Error output for non-HTML formats

To override non-HTML error output, the Serializer component needs to be installed.

HTML 以外のエラー出力をオーバーライドするには、Serializer コンポーネントをインストールする必要があります。
1
$ composer require symfony/serializer-pack

The Serializer component has a built-in FlattenException normalizer (ProblemNormalizer) and JSON/XML/CSV/YAML encoders. When your application throws an exception, Symfony can output it in one of those formats. If you want to change the output contents, create a new Normalizer that supports the FlattenException input:

Serializer コンポーネントには、組み込みの FlattenException ノーマライザー (ProblemNormalizer) と JSON/XML/CSV/YAML エンコーダーがあります。アプリケーションが例外をスローすると、Symfonycan はそれらの形式のいずれかでそれを出力します。 outputcontents を変更する場合は、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;
    }
}

Overriding the Default ErrorController

If you need a little more flexibility beyond just overriding the template, then you can change the controller that renders the error page. For example, you might need to pass some additional variables into your template.

テンプレートをオーバーライドするだけでなく、もう少し柔軟性が必要な場合は、エラー ページをレンダリングするコントローラーを変更できます。たとえば、いくつかの追加変数をテンプレートに渡す必要がある場合があります。

To do this, create a new controller anywhere in your application and set the framework.error_controller configuration option to point to it:

これを行うには、アプリケーションの任意の場所に新しいコントローラーを作成し、framework.error_controller 構成オプションをそれを指すように設定します。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
# config/packages/framework.yaml
framework:
    error_controller: App\Controller\ErrorController::show

The ErrorListener class used by the FrameworkBundle as a listener of the kernel.exception event creates the request that will be dispatched to your controller. In addition, your controller will be passed two parameters:

FrameworkBundle が kernel.exception イベントのリスナーとして使用する ErrorListener クラスは、コントローラーにディスパッチされるリクエストを作成します。さらに、コントローラーには次の 2 つのパラメーターが渡されます。
exception
The original Throwable instance being handled.
処理されている元の Throwable インスタンス。
logger
A DebugLoggerInterface instance which may be null in some circumstances.
状況によっては null になる可能性がある DebugLoggerInterface インスタンス。

Tip

ヒント

The error page preview also works for your own controllers set up this way.

エラー ページのプレビューは、このように設定された独自のコントローラーでも機能します。

Working with the kernel.exception Event

When an exception is thrown, the HttpKernel class catches it and dispatches a kernel.exception event. This gives you the power to convert the exception into a Response in a few different ways.

例外がスローされると、HttpKernel クラスはそれをキャッチし、kernel.exception イベントを送出します。これにより、いくつかの異なる方法で例外をレスポンスに変換することができます。

Working with this event is actually much more powerful than what has been explained before, but also requires a thorough understanding of Symfony internals. Suppose that your code throws specialized exceptions with a particular meaning to your application domain.

このイベントを操作することは、実際には以前に説明したものよりもはるかに強力ですが、Symfony の内部を完全に理解する必要もあります。コードが、アプリケーション ドメインに対して特定の意味を持つ特別な例外をスローするとします。

Writing your own event listener for the kernel.exception event allows you to have a closer look at the exception and take different actions depending on it. Those actions might include logging the exception, redirecting the user to another page or rendering specialized error pages.

kernel.exception イベントの独自のイベント リスナーを作成すると、例外を詳しく調べて、例外に応じてさまざまなアクションを実行できます。これらのアクションには、例外のログ記録、ユーザーの別のページへのリダイレクト、特殊なエラー ページのレンダリングが含まれる場合があります。

Note

ノート

If your listener calls setThrowable() on the ExceptionEvent event, propagation will be stopped and the response will be sent to the client.

リスナーが ExceptionEvent イベントで setThrowable() を呼び出すと、伝播が停止し、応答がクライアントに送信されます。

This approach allows you to create centralized and layered error handling: instead of catching (and handling) the same exceptions in various controllers time and again, you can have just one (or several) listeners deal with them.

このアプローチにより、一元化された階層化されたエラー処理を作成できます。さまざまなコントローラーで同じ例外を何度もキャッチ (および処理) する代わりに、1 つ (または複数) のリスナーでそれらを処理することができます。

Tip

ヒント

See ExceptionListener class code for a real example of an advanced listener of this type. This listener handles various security-related exceptions that are thrown in your application (like AccessDeniedException) and takes measures like redirecting the user to the login page, logging them out and other things.

このタイプの高度なリスナーの実際の例については、ExceptionListenerclass コードを参照してください。このリスナーは、アプリケーションでスローされるさまざまなセキュリティ関連の例外 (AccessDeniedException など) を処理し、ユーザーをログイン ページにリダイレクトする、ユーザーをログに記録するなどの措置を講じます。