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,119 +33,164 @@ 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
45
45
As the profiler serializes data collector instances, you should not
46
46
store objects that cannot be serialized (like PDO objects), or you need
47
47
to provide your own ``serialize() `` method.
48
48
49
- Most of the time , it is convenient to extend
49
+ Most of the times , it is convenient to extend
50
50
:class: `Symfony\\ Component\\ HttpKernel\\ DataCollector\\ DataCollector ` and
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
+ class MyCollector extends DataCollector
55
56
{
56
57
public function collect(Request $request, Response $response, \Exception $exception = null)
57
58
{
58
59
$this->data = array(
59
- 'memory ' => memory_get_peak_usage(true) ,
60
+ 'variable ' => 'value' ,
60
61
);
61
62
}
62
63
63
- public function getMemory ()
64
+ public function getVariable ()
64
65
{
65
- return $this->data['memory '];
66
+ return $this->data['variable '];
66
67
}
67
68
68
69
public function getName()
69
70
{
70
- return 'memory ';
71
+ return 'app.my_collector ';
71
72
}
72
73
}
73
74
74
75
.. _data_collector_tag :
75
76
76
- Enabling custom Data Collectors
77
+ Enabling Custom Data Collectors
77
78
-------------------------------
78
79
79
- To enable a data collector, add it as a regular service in one of your
80
- configuration, and tag it with ``data_collector ``:
80
+ To enable a data collector, define it as a regular service in your application
81
+ and tag it with ``data_collector ``:
81
82
82
83
.. configuration-block ::
83
84
84
85
.. code-block :: yaml
85
86
87
+ # app/config/services.yml
86
88
services :
87
- data_collector.your_collector_name :
88
- class : Fully\Qualified\Collector\Class\Name
89
+ app.my_collector :
90
+ class : AppBundle\DataCollector\MyCollector
89
91
tags :
90
92
- { name: data_collector }
91
93
92
94
.. code-block :: xml
93
95
94
- <service id =" data_collector.your_collector_name" class =" Fully\Qualified\Collector\Class\Name" >
96
+ <!-- app/config/services.xml -->
97
+ <service id =" app.my_collector" class =" AppBundle\DataCollector\MyCollector" >
95
98
<tag name =" data_collector" />
96
99
</service >
97
100
98
101
.. code-block :: php
99
102
103
+ // app/config/services.php
100
104
$container
101
- ->register('data_collector.your_collector_name ', 'Fully\Qualified\Collector\Class\Name ')
105
+ ->register('app.my_collector ', 'AppBundle\DataCollector\MyCollector ')
102
106
->addTag('data_collector')
103
107
;
104
108
105
109
Adding Web Profiler Templates
106
110
-----------------------------
107
111
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:
112
+ The information collected by your data collector can be displayed both in the
113
+ web debug toolbar and in the web profiler. To do so, you need to create a Twig
114
+ template that includes some specific blocks.
115
+
116
+ In the simplest case, you just want to display the information in the toolbar
117
+ without providing a profiler panel:
111
118
112
119
.. code-block :: jinja
113
120
114
- {% extends 'WebProfilerBundle: Profiler: layout.html.twig' %}
121
+ {% extends '@WebProfiler/ Profiler/ layout.html.twig' %}
115
122
116
123
{% block toolbar %}
117
- {# This toolbar item may appear along the top or bottom of the screen.#}
118
124
{% 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>
125
+ <span class="icon"><img src="... " alt=""/></span>
126
+ <span class="sf-toolbar-status">Information </span>
121
127
{% endset %}
122
128
123
129
{% 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>
130
+ <div class="sf-toolbar-info-piece">
131
+ <b>Quick piece of data</b>
132
+ <span>100 units</span>
133
+ </div>
134
+ <div class="sf-toolbar-info-piece">
135
+ <b>Another piece of data </b>
136
+ <span>300 units</span>
137
+ </div>
132
138
{% endset %}
133
139
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 }) }}
140
+ {# the 'link' value set to 'false' means that this panel doesn't show
141
+ a section in the web profiler. #}
142
+ {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: false }) }}
143
+ {% endblock %}
144
+
145
+ The ``toolbar `` block is used to create a panel in the web debug toolbar. The
146
+ inner ``icon `` block defines the content to display right inside the toolbar
147
+ and the ``text `` block defines the content displayed when hovering the mouse
148
+ over that same panel.
149
+
150
+ .. tip ::
151
+
152
+ Built-in collector templates define all their images as embedded base64-encoded
153
+ images. This makes them work everywhere without having to mess with web assets
154
+ links:
155
+
156
+ .. code-block :: html
157
+
158
+ <img src =" data:image/png;base64,..." />
159
+
160
+ You are encouraged to use this same technique for your own toolbar panels.
161
+
162
+ If the toolbar panel includes extended web profiler information, the Twig template
163
+ must also define other blocks:
137
164
165
+ .. code-block :: jinja
166
+
167
+ {% extends '@WebProfiler/Profiler/layout.html.twig' %}
168
+
169
+ {% block toolbar %}
170
+ {% set icon %}
171
+ <span class="icon"><img src="..." alt=""/></span>
172
+ <span class="sf-toolbar-status">Information</span>
173
+ {% endset %}
174
+
175
+ {% set text %}
176
+ <div class="sf-toolbar-info-piece">
177
+ {# ... #}
178
+ </div>
179
+ {% endset %}
180
+
181
+ {# the 'link' value is now set to 'true', which allows the user to click
182
+ on it to access to the web profiler panel. #}
183
+ {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true }) }}
138
184
{% endblock %}
139
185
140
186
{% block head %}
141
- {# Optional, if you need your own JS or CSS files. #}
142
- {{ parent() }} {# Use parent() to keep the default styles #}
187
+ {# Optional, here you can link to or define your own CSS and JS contents #}
143
188
{% endblock %}
144
189
145
190
{% block menu %}
146
191
{# This left-hand menu appears when using the full-screen profiler. #}
147
192
<span class="label">
148
- <span class="icon"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAQAAADVGmdYAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQffAxkBCDStonIVAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAHpJREFUOMtj3PWfgXRAuqZd/5nIsIdhVBPFmgqIjCuYOrJsYtz1fxuUOYER2TQID8afwIiQ8YIkI4TzCv5D2AgaWSuExJKMIDbA7EEVhQEWXJ6FKUY4D48m7HYU/EcWZ8JlE6qfMELPDcUJuEMPxvYazYTDWRMjOcUyAEswO+VjeQQaAAAAAElFTkSuQmCC " alt=""/></span>
193
+ <span class="icon"><img src="... " alt=""/></span>
149
194
<strong>Example Collector</strong>
150
195
</span>
151
196
{% endblock %}
@@ -158,58 +203,76 @@ following example can help you get started:
158
203
</p>
159
204
{% endblock %}
160
205
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
-
206
+ The ``menu `` and ``panel `` blocks are the only required blocks to define the
207
+ contents displayed in the web profiler panel associated with this data collector.
165
208
All blocks have access to the ``collector `` object.
166
209
167
- .. tip ::
210
+ Finally, to enable the data collector template, add a ``template `` attribute to
211
+ the ``data_collector `` tag in your service configuration:
168
212
169
- Built-in templates use a base64 encoded image for the toolbar :
213
+ .. configuration-block : :
170
214
171
- .. code-block :: html
215
+ .. code-block :: yaml
172
216
173
- <img src =" data:image/png;base64,..." />
217
+ # app/config/services.yml
218
+ services :
219
+ app.my_collector :
220
+ class : AppBundle\DataCollector\MyCollector
221
+ tags :
222
+ - { name: data_collector, template: 'data_collector/template.html.twig', id: 'app.my_collector' }
223
+
224
+ .. code-block :: xml
225
+
226
+ <!-- app/config/services.xml -->
227
+ <service id =" app.my_collector" class =" AppBundle\DataCollector\MyCollector" >
228
+ <tag name =" data_collector" template =" data_collector/template.html.twig" id =" app.my_collector" />
229
+ </service >
174
230
175
- You can easily calculate the base64 value for an image with this
176
- little script::
231
+ .. code-block :: php
177
232
178
- #!/usr/bin/env php
179
- <?php
180
- echo base64_encode(file_get_contents($_SERVER['argv'][1]));
233
+ // app/config/services.php
234
+ $container
235
+ ->register('app.my_collector', 'AppBundle\DataCollector\MyCollector')
236
+ ->addTag('data_collector', array(
237
+ 'template' => 'data_collector/template.html.twig',
238
+ 'id' => 'app.my_collector',
239
+ ))
240
+ ;
181
241
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 some
184
- AcmeDebugBundle:
242
+ .. caution ::
243
+
244
+ The ``id `` attribute must match the value returned by the ``getName() `` method.
245
+
246
+ The position of each panel in the toolbar is determined by the priority defined
247
+ by each collector. Most built-in collectors use ``255 `` as their priority. If you
248
+ want your collector to be displayed before them, use a higher value:
185
249
186
250
.. configuration-block ::
187
251
188
252
.. code-block :: yaml
189
253
254
+ # app/config/services.yml
190
255
services :
191
- data_collector.your_collector_name :
192
- class : Acme\DebugBundle\Collector\Class\Name
256
+ app.my_collector :
257
+ class : AppBundle\DataCollector\MyCollector
193
258
tags :
194
- - { name: data_collector, template: "AcmeDebugBundle:Collector:templatename" , id: "your_collector_name" }
259
+ - { name: data_collector, template: '...' , id: '...', priority: '300' }
195
260
196
261
.. code-block :: xml
197
262
198
- <service id =" data_collector.your_collector_name" class =" Acme\DebugBundle\Collector\Class\Name" >
199
- <tag name =" data_collector" template =" AcmeDebugBundle:Collector:templatename" id =" your_collector_name" />
263
+ <!-- app/config/services.xml -->
264
+ <service id =" app.my_collector" class =" AppBundle\DataCollector\MyCollector" >
265
+ <tag name =" data_collector" template =" ..." id =" ..." priority =" 300" />
200
266
</service >
201
267
202
268
.. code-block :: php
203
269
270
+ // app/config/services.php
204
271
$container
205
- ->register('data_collector.your_collector_name ', 'Acme\DebugBundle\Collector\Class\Name ')
272
+ ->register('app.my_collector ', 'AppBundle\DataCollector\MyCollector ')
206
273
->addTag('data_collector', array(
207
- 'template' => 'AcmeDebugBundle:Collector:templatename',
208
- 'id' => 'your_collector_name',
274
+ 'template' => '...',
275
+ 'id' => '...',
276
+ 'priority' => 300,
209
277
))
210
278
;
211
-
212
- .. caution ::
213
-
214
- Make sure the ``id `` attribute is the same string you used for the
215
- ``getName() `` method.
0 commit comments