4
4
How to Create a custom Data Collector
5
5
=====================================
6
6
7
- :doc: `The Symfony Profiler </cookbook/profiler/index >` delegates data collecting to
8
- data collectors. Symfony comes bundled with a few of them, but you can easily
9
- create your own.
7
+ :doc: `The Symfony Profiler </cookbook/profiler/index >` delegates data collection
8
+ to some special classes called data collectors. Symfony comes bundled with a few
9
+ of them, but you can easily create your own.
10
10
11
11
Creating a custom Data Collector
12
12
--------------------------------
@@ -33,12 +33,12 @@ Creating a custom data collector is as simple as implementing the
33
33
function getName();
34
34
}
35
35
36
- The ``getName() `` method must return a unique name . This is used to access the
37
- information later on (see :doc: `/cookbook/testing/profiling ` for
38
- instance).
36
+ The value returned by ``getName() `` must be unique in the application . This value
37
+ is also used to access the information later on (see :doc: `/cookbook/testing/profiling `
38
+ for instance).
39
39
40
- The ``collect() `` method is responsible for storing the data it wants to give
41
- access to in local properties.
40
+ The ``collect() `` method is responsible for storing the collected data in local
41
+ properties.
42
42
43
43
.. caution ::
44
44
@@ -51,101 +51,169 @@ Most of the time, it is convenient to extend
51
51
populate the ``$this->data `` property (it takes care of serializing the
52
52
``$this->data `` property)::
53
53
54
- class MemoryDataCollector extends DataCollector
54
+ // src/AppBundle/DataCollector/MyCollector.php
55
+ use Symfony\Component\HttpKernel\DataCollector\DataCollector;
56
+
57
+ class MyCollector extends DataCollector
55
58
{
56
59
public function collect(Request $request, Response $response, \Exception $exception = null)
57
60
{
58
61
$this->data = array(
59
- 'memory ' => memory_get_peak_usage(true) ,
62
+ 'variable ' => 'value' ,
60
63
);
61
64
}
62
65
63
- public function getMemory ()
66
+ public function getVariable ()
64
67
{
65
- return $this->data['memory '];
68
+ return $this->data['variable '];
66
69
}
67
70
68
71
public function getName()
69
72
{
70
- return 'memory ';
73
+ return 'app.my_collector ';
71
74
}
72
75
}
73
76
74
77
.. _data_collector_tag :
75
78
76
- Enabling custom Data Collectors
79
+ Enabling Custom Data Collectors
77
80
-------------------------------
78
81
79
- To enable a data collector, add it as a regular service in one of your
80
- configuration, and tag it with ``data_collector ``:
82
+ To enable a data collector, define it as a regular service and tag it with
83
+ ``data_collector ``:
81
84
82
85
.. configuration-block ::
83
86
84
87
.. code-block :: yaml
85
88
89
+ # app/config/services.yml
86
90
services :
87
- data_collector.your_collector_name :
88
- class : Fully\Qualified\Collector\Class\Name
91
+ app.my_collector :
92
+ class : AppBundle\DataCollector\MyCollector
93
+ public : false
89
94
tags :
90
95
- { name: data_collector }
91
96
92
97
.. code-block :: xml
93
98
94
- <service id =" data_collector.your_collector_name" class =" Fully\Qualified\Collector\Class\Name" >
95
- <tag name =" data_collector" />
96
- </service >
99
+ <!-- app/config/services.xml -->
100
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
101
+ <container xmlns =" http://symfony.com/schema/dic/services"
102
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
103
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
104
+ http://symfony.com/schema/dic/services/services-1.0.xsd"
105
+ >
106
+ <services >
107
+ <service id =" app.my_collector" class =" AppBundle\DataCollector\MyCollector"
108
+ public =" false" >
109
+ <tag name =" data_collector" />
110
+ </service >
111
+ </services >
112
+ </container >
97
113
98
114
.. code-block :: php
99
115
116
+ // app/config/services.php
100
117
$container
101
- ->register('data_collector.your_collector_name', 'Fully\Qualified\Collector\Class\Name')
118
+ ->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
119
+ ->setPublic(false)
102
120
->addTag('data_collector')
103
121
;
104
122
105
123
Adding Web Profiler Templates
106
124
-----------------------------
107
125
108
- When you want to display the data collected by your data collector in the web
109
- debug toolbar or the web profiler, you will need to create a Twig template. The
110
- following example can help you get started:
126
+ The information collected by your data collector can be displayed both in the
127
+ web debug toolbar and in the web profiler. To do so, you need to create a Twig
128
+ template that includes some specific blocks.
129
+
130
+ In the simplest case, you just want to display the information in the toolbar
131
+ without providing a profiler panel. This requires to define the ``toolbar ``
132
+ block and set the value of two variables called ``icon `` and ``text ``:
111
133
112
- .. code-block :: jinja
134
+ .. code-block :: html+ jinja
113
135
114
136
{% extends 'WebProfilerBundle:Profiler: layout.html.twig' %}
115
137
116
138
{% block toolbar %}
117
- {# This toolbar item may appear along the top or bottom of the screen.#}
118
139
{% set icon %}
119
- <span class="icon"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAQAAADVGmdYAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQffAxkBCDStonIVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAHpJREFUOMtj3PWfgXRAuqZd/5nIsIdhVBPFmgqIjCuYOrJsYtz1fxuUOYER2TQID8afwIiQ8YIkI4TzCv5D2AgaWSuExJKMIDbA7EEVhQEWXJ6FKUY4D48m7HYU/EcWZ8JlE6qfMELPDcUJuEMPxvYazYTDWRMjOcUyAEswO+VjeQQaAAAAAElFTkSuQmCC" alt=""/></span>
120
- <span class="sf-toolbar-status">Example</span>
140
+ {# this is the content displayed as a panel in the toolbar #}
141
+ <span class="icon"><img src="..." alt=""/></span>
142
+ <span class="sf-toolbar-status">Information</span>
121
143
{% endset %}
122
144
123
145
{% set text %}
124
- <div class="sf-toolbar-info-piece">
125
- <b>Quick piece of data</b>
126
- <span>100 units</span>
127
- </div>
128
- <div class="sf-toolbar-info-piece">
129
- <b>Another quick thing</b>
130
- <span>300 units</span>
131
- </div>
146
+ {# this is the content displayed when hovering the mouse over
147
+ the toolbar panel #}
148
+ <div class="sf-toolbar-info-piece">
149
+ <b>Quick piece of data</b>
150
+ <span>100 units</span>
151
+ </div>
152
+ <div class="sf-toolbar-info-piece">
153
+ <b>Another piece of data</b>
154
+ <span>300 units</span>
155
+ </div>
132
156
{% endset %}
133
157
134
- {# Set the "link" value to false if you do not have a big "panel"
135
- section that you want to direct the user to. #}
136
- {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
158
+ {# the 'link' value set to 'false' means that this panel doesn't
159
+ show a section in the web profiler. #}
160
+ {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }}
161
+ {% endblock %}
162
+
163
+ .. tip ::
164
+
165
+ Built-in collector templates define all their images as embedded base64-encoded
166
+ images. This makes them work everywhere without having to mess with web assets
167
+ links:
168
+
169
+ .. code-block :: html
170
+
171
+ <img src =" data:image/png;base64,..." />
172
+
173
+ Another solution is to define the images as SVG files. In addition to being
174
+ resolution-independent, these images can be easily embedded in the Twig
175
+ template or included from an external file to reuse them in several templates:
137
176
177
+ .. code-block :: jinja
178
+
179
+ {{ include('@App/data_collector/icon.svg') }}
180
+
181
+ You are encouraged to use the latter technique for your own toolbar panels.
182
+
183
+ If the toolbar panel includes extended web profiler information, the Twig template
184
+ must also define additional blocks:
185
+
186
+ .. code-block :: html+jinja
187
+
188
+ {% extends '@WebProfiler/Profiler/layout.html.twig' %}
189
+
190
+ {% block toolbar %}
191
+ {% set icon %}
192
+ <span class="icon"><img src="..." alt=""/></span>
193
+ <span class="sf-toolbar-status">Information</span>
194
+ {% endset %}
195
+
196
+ {% set text %}
197
+ <div class="sf-toolbar-info-piece">
198
+ {# ... #}
199
+ </div>
200
+ {% endset %}
201
+
202
+ {# the 'link' value is now set to 'true', which allows the user to click
203
+ on it to access the web profiler panel. Since 'true' is the default
204
+ value, you can omit the 'link' parameter entirely #}
205
+ {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true }) }}
138
206
{% endblock %}
139
207
140
208
{% block head %}
141
- {# Optional, if you need your own JS or CSS files. #}
142
- {{ parent() }} {# Use parent() to keep the default styles #}
209
+ {# Optional, you can here link to or define your own CSS and JS contents #}
210
+ {# {{ parent() }} to keep the default styles #}
143
211
{% endblock %}
144
212
145
213
{% block menu %}
146
214
{# This left-hand menu appears when using the full-screen profiler. #}
147
215
<span class="label">
148
- <span class="icon"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAQAAADVGmdYAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQffAxkBCDStonIVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAHpJREFUOMtj3PWfgXRAuqZd/5nIsIdhVBPFmgqIjCuYOrJsYtz1fxuUOYER2TQID8afwIiQ8YIkI4TzCv5D2AgaWSuExJKMIDbA7EEVhQEWXJ6FKUY4D48m7HYU/EcWZ8JlE6qfMELPDcUJuEMPxvYazYTDWRMjOcUyAEswO+VjeQQaAAAAAElFTkSuQmCC " alt=""/></span>
216
+ <span class="icon"><img src="... " alt=""/></span>
149
217
<strong>Example Collector</strong>
150
218
</span>
151
219
{% endblock %}
@@ -158,57 +226,90 @@ following example can help you get started:
158
226
</p>
159
227
{% endblock %}
160
228
161
- Each block is optional. The ``toolbar `` block is used for the web debug
162
- toolbar and ``menu `` and ``panel `` are used to add a panel to the web
163
- profiler.
164
-
229
+ The ``menu `` and ``panel `` blocks are the only required blocks to define the
230
+ contents displayed in the web profiler panel associated with this data collector.
165
231
All blocks have access to the ``collector `` object.
166
232
167
- .. tip ::
233
+ Finally, to enable the data collector template, add a ``template `` attribute to
234
+ the ``data_collector `` tag in your service configuration:
168
235
169
- Built-in templates use a base64 encoded image for the toolbar :
236
+ .. configuration-block : :
170
237
171
- .. code-block :: html
238
+ .. code-block :: yaml
172
239
173
- <img src =" data:image/png;base64,..." />
240
+ # app/config/services.yml
241
+ services :
242
+ app.my_collector :
243
+ class : AppBundle\DataCollector\MyCollector
244
+ tags :
245
+ -
246
+ name : data_collector
247
+ template : ' data_collector/template.html.twig'
248
+ id : ' app.my_collector'
249
+ public : false
174
250
175
- You can easily calculate the base64 value for an image with this
176
- little script::
251
+ .. code-block :: xml
177
252
178
- #!/usr/bin/env php
179
- <?php
180
- echo base64_encode(file_get_contents($_SERVER['argv'][1]));
253
+ <!-- app/config/services.xml -->
254
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
255
+ <container xmlns =" http://symfony.com/schema/dic/services"
256
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
257
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
258
+ http://symfony.com/schema/dic/services/services-1.0.xsd"
259
+ >
260
+ <services >
261
+ <service id =" app.my_collector" class =" AppBundle\DataCollector\MyCollector" public =" false" >
262
+ <tag name =" data_collector" template =" data_collector/template.html.twig" id =" app.my_collector" />
263
+ </service >
264
+ </services >
265
+ </container >
181
266
182
- To enable the template, add a ``template `` attribute to the ``data_collector ``
183
- tag in your configuration. For example, assuming your template is in AppBundle:
267
+ .. code-block :: php
268
+
269
+ // app/config/services.php
270
+ $container
271
+ ->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
272
+ ->setPublic(false)
273
+ ->addTag('data_collector', array(
274
+ 'template' => 'data_collector/template.html.twig',
275
+ 'id' => 'app.my_collector',
276
+ ))
277
+ ;
278
+
279
+ .. caution ::
280
+
281
+ The ``id `` attribute must match the value returned by the ``getName() `` method.
282
+
283
+ The position of each panel in the toolbar is determined by the priority defined
284
+ by each collector. Most built-in collectors use ``255 `` as their priority. If you
285
+ want your collector to be displayed before them, use a higher value:
184
286
185
287
.. configuration-block ::
186
288
187
289
.. code-block :: yaml
188
290
291
+ # app/config/services.yml
189
292
services :
190
- data_collector.your_collector_name :
191
- class : AppBundle\Collector\Class\Name
293
+ app.my_collector :
294
+ class : AppBundle\DataCollector\MyCollector
192
295
tags :
193
- - { name: data_collector, template: "AppBundle:Collector:templatename" , id: "your_collector_name" }
296
+ - { name: data_collector, template: '...' , id: '...', priority: 300 }
194
297
195
298
.. code-block :: xml
196
299
197
- <service id =" data_collector.your_collector_name" class =" AppBundle\Collector\Class\Name" >
198
- <tag name =" data_collector" template =" AppBundle:Collector:templatename" id =" your_collector_name" />
300
+ <!-- app/config/services.xml -->
301
+ <service id =" app.my_collector" class =" AppBundle\DataCollector\MyCollector" >
302
+ <tag name =" data_collector" template =" ..." id =" ..." priority =" 300" />
199
303
</service >
200
304
201
305
.. code-block :: php
202
306
307
+ // app/config/services.php
203
308
$container
204
- ->register('data_collector.your_collector_name ', 'AppBundle\Collector\Class\Name ')
309
+ ->register('app.my_collector ', 'AppBundle\DataCollector\MyCollector ')
205
310
->addTag('data_collector', array(
206
- 'template' => 'AppBundle:Collector:templatename',
207
- 'id' => 'your_collector_name',
311
+ 'template' => '...',
312
+ 'id' => '...',
313
+ 'priority' => 300,
208
314
))
209
315
;
210
-
211
- .. caution ::
212
-
213
- Make sure the ``id `` attribute is the same string you used for the
214
- ``getName() `` method.
0 commit comments