How to Create a custom Data Collector

The Symfony Profiler obtains its profiling and debug information using some special classes called data collectors. Symfony comes bundled with a few of them, but you can also create your own.

Symfony プロファイラーは、データ コレクターと呼ばれるいくつかの特別なクラスを使用して、プロファイリングとデバッグ情報を取得します。 symfony にはそれらのいくつかがバンドルされていますが、独自のものを作成することもできます。

Creating a custom Data Collector

A data collector is a PHP class that implements the DataCollectorInterface. For convenience, your data collectors can also extend from the AbstractDataCollector class, which implements the interface and provides some utilities and the $this->data property to store the collected information.

データ コレクターは、DataCollectorInterface を実装する PHP クラスです。便宜上、データ コレクターは、AbstractDataCollector クラスから拡張することもできます。AbstractDataCollector クラスは、インターフェイスを実装し、収集された情報を格納するためのいくつかのユーティリティと $this->data プロパティを提供します。

The following example shows a custom collector that stores information about the request:

次の例は、リクエストに関する情報を格納するカスタム コレクターを示しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/DataCollector/RequestCollector.php
namespace App\DataCollector;

use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class RequestCollector extends AbstractDataCollector
{
    public function collect(Request $request, Response $response, \Throwable $exception = null)
    {
        $this->data = [
            'method' => $request->getMethod(),
            'acceptable_content_types' => $request->getAcceptableContentTypes(),
        ];
    }
}

These are the method that you can define in the data collector class:

これらは、データ コレクター クラスで定義できるメソッドです。
collect() method:

Stores the collected data in local properties ($this->data if you extend from AbstractDataCollector). If you need some services to collect the data, inject those services in the data collector constructor.

収集したデータをローカル プロパティに格納します (AbstractDataCollector から拡張する場合は $this->data)。データを収集するためにいくつかのサービスが必要な場合は、それらのサービスをデータ コレクター コンストラクターに挿入します。

Caution

注意

The collect() method is only called once. It is not used to "gather" data but is there to "pick up" the data that has been stored by your service.

collect() メソッドは 1 回だけ呼び出されます。データを「収集」するために使用されるのではなく、サービスによって保存されたデータを「ピックアップ」するために使用されます。

Caution

注意

As the profiler serializes data collector instances, you should not store objects that cannot be serialized (like PDO objects) or you need to provide your own serialize() method.

プロファイラーはデータ コレクター インスタンスをシリアル化するため、シリアル化できないオブジェクト (PDO オブジェクトなど) を保存しないか、独自の serialize() メソッドを提供する必要があります。
reset() method:
It's called between requests to reset the state of the profiler. By default it only empties the $this->data contents, but you can override this method to do additional cleaning.
プロファイラーの状態をリセットするために、リクエスト間で呼び出されます。デフォルトでは、$this->data の内容のみを空にしますが、このメソッドをオーバーライドして追加のクリーニングを行うことができます。
getName() method:
Returns the collector identifier, which must be unique in the application. By default it returns the FQCN of the data collector class, but you can override this method to return a custom name (e.g. app.request_collector). This value is used later to access the collector information (see How to Use the Profiler in a Functional Test) so you may prefer using short strings instead of FQCN strings.
アプリケーション内で一意である必要があるコレクター識別子を返します。デフォルトでは、データ コレクター クラスの FQCN を返しますが、このメソッドをオーバーライドしてカスタム名 (app.request_collector など) を返すことができます。この値は、後でアクセスするために使用されます。コレクター情報 (「機能テストでプロファイラーを使用する方法」を参照) を使用するため、FQCN 文字列の代わりに短い文字列を使用することをお勧めします。

The collect() method is called during the kernel.response event. If you need to collect data that is only available later, implement LateDataCollectorInterface and define the lateCollect() method, which is invoked right before the profiler data serialization (during kernel.terminate event).

collect() メソッドは、kernel.responseevent 中に呼び出されます。後でしか利用できないデータを収集する必要がある場合は、LateDataCollectorInterface を実装し、lateCollect() メソッドを定義します。このメソッドは、プロファイラーデータのシリアル化の直前 (kernel.terminate イベント中) に呼び出されます。

Note

ノート

If you're using the default services.yaml configuration with autoconfigure, then Symfony will start using your data collector after the next page refresh. Otherwise, enable the data collector by hand.

autoconfigure でデフォルトの services.yaml 設定を使用している場合、Symfony は次のページ更新後にデータ コレクターの使用を開始します。それ以外の場合は、手動でデータ コレクターを有効にします。

Adding Web Profiler Templates

The information collected by your data collector can be displayed both in the web debug toolbar and in the web profiler. To do so, you need to create a Twig template that includes some specific blocks.

データ コレクターによって収集された情報は、Web デバッグ ツールバーと Web プロファイラーの両方に表示できます。そのためには、いくつかの特定のブロックを含む Twigtemplate を作成する必要があります。

First, add the getTemplate() method in your data collector class to return the path of the Twig template to use. Then, add some getters to give the template access to the collected information:

まず、データ コレクター クラスに getTemplate() メソッドを追加して、使用する Twig テンプレートのパスを返します。次に、いくつかの getter を追加して、テンプレートが収集された情報にアクセスできるようにします。
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/DataCollector/RequestCollector.php
namespace App\DataCollector;

use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;

class RequestCollector extends AbstractDataCollector
{
    // ...

    public static function getTemplate(): ?string
    {
        return 'data_collector/template.html.twig';
    }

    public function getMethod()
    {
        return $this->data['method'];
    }

    public function getAcceptableContentTypes()
    {
        return $this->data['acceptable_content_types'];
    }
}

In the simplest case, you want to display the information in the toolbar without providing a profiler panel. This requires to define the toolbar block and set the value of two variables called icon and text:

最も単純なケースでは、プロファイラー パネルを提供せずにツールバーに情報を表示します。これには、toolbarblock を定義し、icon と text という 2 つの変数の値を設定する必要があります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{# templates/data_collector/template.html.twig #}
{% extends '@WebProfiler/Profiler/layout.html.twig' %}

{% block toolbar %}
    {% set icon %}
        {# this is the content displayed as a panel in the toolbar #}
        <svg xmlns="http://www.w3.org/2000/svg"> ... </svg>
        <span class="sf-toolbar-value">Request</span>
    {% endset %}

    {% set text %}
        {# this is the content displayed when hovering the mouse over
           the toolbar panel #}
        <div class="sf-toolbar-info-piece">
            <b>Method</b>
            <span>{{ collector.method }}</span>
        </div>

        <div class="sf-toolbar-info-piece">
            <b>Accepted content type</b>
            <span>{{ collector.acceptableContentTypes|join(', ') }}</span>
        </div>
    {% endset %}

    {# the 'link' value set to 'false' means that this panel doesn't
       show a section in the web profiler #}
    {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }}
{% endblock %}

Tip

ヒント

Built-in collector templates define all their images as embedded SVG files. This makes them work everywhere without having to mess with web assets links:

組み込みのコレクター テンプレートは、すべての画像を埋め込み SVG ファイルとして定義します。これにより、Web アセット リンクをいじる必要なく、どこでも機能します。
1
2
3
4
{% set icon %}
    {{ include('data_collector/icon.svg') }}
    {# ... #}
{% endset %}

If the toolbar panel includes extended web profiler information, the Twig template must also define additional blocks:

ツールバー パネルに拡張された Web プロファイラー情報が含まれている場合、Twig テンプレートは追加のブロックも定義する必要があります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{# templates/data_collector/template.html.twig #}
{% extends '@WebProfiler/Profiler/layout.html.twig' %}

{% block toolbar %}
    {% set icon %}
        {# ... #}
    {% endset %}

    {% set text %}
        <div class="sf-toolbar-info-piece">
            {# ... #}
        </div>
    {% endset %}

    {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
{% endblock %}

{% block head %}
    {# Optional. Here you can link to or define your own CSS and JS contents. #}
    {# Use {{ parent() }} to extend the default styles instead of overriding them. #}
{% endblock %}

{% block menu %}
    {# This left-hand menu appears when using the full-screen profiler. #}
    <span class="label">
        <span class="icon"><img src="..." alt=""/></span>
        <strong>Request</strong>
    </span>
{% endblock %}

{% block panel %}
    {# Optional, for showing the most details. #}
    <h2>Acceptable Content Types</h2>
    <table>
        <tr>
            <th>Content Type</th>
        </tr>

        {% for type in collector.acceptableContentTypes %}
        <tr>
            <td>{{ type }}</td>
        </tr>
        {% endfor %}
    </table>
{% endblock %}

The menu and panel blocks are the only required blocks to define the contents displayed in the web profiler panel associated with this data collector. All blocks have access to the collector object.

メニュー ブロックとパネル ブロックは、このデータ コレクターに関連付けられた Web プロファイラー パネルに表示されるコンテンツを定義するために必要な唯一のブロックです。すべてのブロックがコレクター オブジェクトにアクセスできます。

Note

ノート

The position of each panel in the toolbar is determined by the collector priority, which can only be defined when configuring the data collector by hand.

ツールバー内の各パネルの位置は、コレクターの優先度によって決定されます。これは、データ コレクターを手動で構成する場合にのみ定義できます。

Note

ノート

If you're using the default services.yaml configuration with autoconfigure, then Symfony will start displaying your collector data in the toolbar after the next page refresh. Otherwise, enable the data collector by hand.

autoconfigure でデフォルトの services.yaml 設定を使用している場合、Symfony は次のページ更新後にツールバーにコレクタ データを表示し始めます。それ以外の場合は、手動でデータ コレクターを有効にします。

Enabling Custom Data Collectors

If you don't use Symfony's default configuration with autowire and autoconfigure you'll need to configure the data collector explicitly:

autowire および autoconfigure で Symfony のデフォルト設定を使用しない場合は、データ コレクターを明示的に設定する必要があります。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
# config/services.yaml
services:
    App\DataCollector\RequestCollector:
        tags:
            -
                name: data_collector
                # must match the value returned by the getName() method
                id: 'App\DataCollector\RequestCollector'
                # optional template (it has more priority than the value returned by getTemplate())
                template: 'data_collector/template.html.twig'
                # optional priority (positive or negative integer; default = 0)
                # priority: 300