Skip to content

Commit d1afa4d

Browse files
committed
feature #4243 [WIP] var-dumper component (nicolas-grekas)
This PR was merged into the master branch. Discussion ---------- [WIP] var-dumper component | Q | A | ------------- | --- | Doc fix? | no | New docs? | yes | Applies to | 2.6 | Fixed tickets | none - [x] general introduction - [x] cloner doc - [x] caster doc - [x] dumper doc - [x] config doc - [x] example output with explanations Commits ------- 041e858 add examples 23712fb more accurate doc about limits c578fe7 how to dump as string note edb0ff9 minor adjustments 6a3e170 § about DebugBundle config cb0ee89 § about Data::getLimitedClone() ee2d7e4 section for DebugBundle/Twig integration b5b45bc move Dumper section above the Caster one 2fc3811 use VarCloner instead of Php/ExtCloner 350e0c7 split intro/advanced sections 036edcb doc for Dumpers 7dc6e5c Reduce line length 5e0b9bd review effect 26edf7a intro the var-dumper component
2 parents 5d43069 + 041e858 commit d1afa4d

14 files changed

+430
-0
lines changed

components/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ The Components
2929
stopwatch
3030
templating/index
3131
translation/index
32+
var_dumper/index
3233
yaml/index
3334

3435
.. include:: /components/map.rst.inc

components/map.rst.inc

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@
144144
* :doc:`/components/translation/usage`
145145
* :doc:`/components/translation/custom_formats`
146146

147+
* :doc:`/components/var_dumper/index`
148+
149+
* :doc:`/components/var_dumper/introduction`
150+
* :doc:`/components/var_dumper/advanced`
151+
147152
* :doc:`/components/yaml/index`
148153

149154
* :doc:`/components/yaml/introduction`

components/var_dumper/advanced.rst

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
.. index::
2+
single: VarDumper
3+
single: Components; VarDumper
4+
5+
Advanced Usage of the VarDumper Component
6+
=========================================
7+
8+
``dump()`` function is just a thin wrapper and a more convenient way to call
9+
:method:`VarDumper::dump() <Symfony\\Component\\VarDumper\\VarDumper::dump>`.
10+
You can change the behavior of this function by calling
11+
:method:`VarDumper::setHandler($callable) <Symfony\\Component\\VarDumper\\VarDumper::setHandler>`:
12+
calls to ``dump()`` will then be forwarded to ``$callable``.
13+
14+
Cloners
15+
~~~~~~~
16+
17+
A cloner is used to create an intermediate representation of any PHP variable.
18+
Its output is a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data`
19+
object that wraps this representation.
20+
21+
You can create a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data`
22+
object this way::
23+
24+
$cloner = new VarCloner();
25+
$data = $cloner->cloneVar($myVar);
26+
27+
A cloner also applies limits when creating this representation, so that the
28+
corresponding Data object could represent only a subset of the cloned variable.
29+
Before :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::cloneVar`,
30+
you can configure these limits:
31+
32+
* :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::setMaxItems`
33+
configures the maximum number of items that will be cloned *past the first
34+
nesting level*. Items are counted using a breadth-first algorithm so that
35+
lower level items have higher priority than deeply nested items;
36+
* :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::setMaxString`
37+
configures the maximum number of characters that will be cloned before
38+
cutting overlong strings;
39+
* in both cases, specifying `-1` removes any limit.
40+
41+
Before dumping it, you can further limit the resulting
42+
:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object by calling its
43+
:method:`Symfony\\Component\\VarDumper\\Cloner\\Data::getLimitedClone`
44+
method:
45+
46+
* the first ``$maxDepth`` argument allows limiting dumps in the depth dimension,
47+
* the second ``$maxItemsPerDepth`` limits the number of items per depth level,
48+
* and the last ``$useRefHandles`` defaults to ``true`` but allows removing
49+
internal objects' handles for sparser output,
50+
* but unlike the previous limits on cloners that remove data on purpose,
51+
these can be changed back and forth before dumping since they do not affect
52+
the intermediate representation internally.
53+
54+
.. note::
55+
56+
When no limit is applied, a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data`
57+
object is as accurate as the native :phpfunction:`serialize` function
58+
and thus could have a wider purpose than strictly dumping for debugging.
59+
60+
Dumpers
61+
~~~~~~~
62+
63+
A dumper is responsible for outputting a string representation of a PHP variable,
64+
using a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object as input.
65+
The destination and the formatting of this output vary with dumpers.
66+
67+
This component comes with an :class:`Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper`
68+
for HTML output and a :class:`Symfony\\Component\\VarDumper\\Dumper\\CliDumper`
69+
for optionally colored command line output.
70+
71+
For example, if you want to dump some ``$variable``, just do::
72+
73+
$cloner = new VarCloner();
74+
$dumper = new CliDumper();
75+
76+
$dumper->dump($cloner->cloneVar($variable));
77+
78+
By using the first argument of the constructor, you can select the output
79+
stream where the dump will be written. By default, the ``CliDumper`` writes
80+
on ``php://stdout`` and the ``HtmlDumper`` on ``php://output``, but any PHP
81+
stream (resource or URL) is acceptable.
82+
83+
Instead of a stream destination, you can also pass it a ``callable`` that
84+
will be called repeatedly for each line generated by a dumper. This
85+
callable can be configured using the first argument of a dumper's constructor,
86+
but also using the
87+
:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::setOutput`
88+
method or the second argument of the
89+
:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::dump` method.
90+
91+
For example, to get a dump as a string in a variable, you can do::
92+
93+
$cloner = new VarCloner();
94+
$dumper = new CliDumper();
95+
$output = '';
96+
97+
$dumper->dump(
98+
$cloner->cloneVar($variable),
99+
function ($line, $depth) use (&$output) {
100+
// A negative depth means "end of dump"
101+
if ($depth >= 0) {
102+
// Adds a two spaces indentation to the line
103+
$output .= str_repeat(' ', $depth).$line."\n";
104+
}
105+
}
106+
);
107+
108+
// $output is now populated with the dump representation of $variable
109+
110+
An other option for doing the same could be::
111+
112+
cloner = new VarCloner();
113+
$dumper = new CliDumper();
114+
$output = fopen('php://memory', 'r+b');
115+
116+
$dumper->dump($cloner->cloneVar($variable), $output);
117+
rewind($output);
118+
$output = stream_get_contents($output);
119+
120+
// $output is now populated with the dump representation of $variable
121+
122+
Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface`
123+
interface that specifies the
124+
:method:`dump(Data $data) <Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface::dump>`
125+
method. They also typically implement the
126+
:class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees
127+
them from re-implementing the logic required to walk through a
128+
:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure.
129+
130+
Casters
131+
~~~~~~~
132+
133+
Objects and resources nested in a PHP variable are casted to arrays in the
134+
intermediate :class:`Symfony\\Component\\VarDumper\\Cloner\\Data`
135+
representation. You can tweak the array representation for each object/resource
136+
by hooking a Caster into this process. The component already includes many
137+
casters for base PHP classes and other common classes.
138+
139+
If you want to build your own Caster, you can register one before cloning
140+
a PHP variable. Casters are registered using either a Cloner's constructor
141+
or its ``addCasters()`` method::
142+
143+
$myCasters = array(...);
144+
$cloner = new VarCloner($myCasters);
145+
146+
// or
147+
148+
$cloner->addCasters($myCasters);
149+
150+
The provided ``$myCasters`` argument is an array that maps a class,
151+
an interface or a resource type to a callable::
152+
153+
$myCasters = array(
154+
'FooClass' => $myFooClassCallableCaster,
155+
':bar resource' => $myBarResourceCallableCaster,
156+
);
157+
158+
As you can notice, resource types are prefixed by a ``:`` to prevent
159+
colliding with a class name.
160+
161+
Because an object has one main class and potentially many parent classes
162+
or interfaces, many casters can be applied to one object. In this case,
163+
casters are called one after the other, starting from casters bound to the
164+
interfaces, the parents classes and then the main class. Several casters
165+
can also be registered for the same resource type/class/interface.
166+
They are called in registration order.
167+
168+
Casters are responsible for returning the properties of the object or resource
169+
being cloned in an array. They are callables that accept four arguments:
170+
171+
* the object or resource being casted,
172+
* an array modelled for objects after PHP's native ``(array)`` cast operator,
173+
* a :class:`Symfony\\Component\\VarDumper\\Cloner\\Stub` object
174+
representing the main properties of the object (class, type, etc.),
175+
* true/false when the caster is called nested is a structure or not.
176+
177+
Here is a simple caster not doing anything::
178+
179+
function myCaster($object, $array, $stub, $isNested)
180+
{
181+
// ... populate/alter $array to your needs
182+
183+
return $array;
184+
}
185+
186+
For objects, the ``$array`` parameter comes pre-populated using PHP's native
187+
``(array)`` casting operator or with the return value of ``$object->__debugInfo()``
188+
if the magic method exists. Then, the return value of one Caster is given
189+
as argument to the next Caster in the chain.
190+
191+
When casting with the ``(array)`` operator, PHP prefixes protected properties
192+
with a ``\0*\0`` and private ones with the class owning the property:
193+
e.g. ``\0Foobar\0`` prefixes all private properties of objects of type Foobar.
194+
Casters follow this convention and add two more prefixes: ``\0~\0`` is used
195+
for virtual properties and ``\0+\0`` for dynamic ones (runtime added
196+
properties not in the class declaration).
197+
198+
.. note::
199+
200+
Although you can, it is best advised not to alter the state of an object
201+
while casting it in a Caster.
202+
203+
.. tip::
204+
205+
Before writting your own casters, you should check the existing ones.

components/var_dumper/index.rst

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
VarDumper
2+
=========
3+
4+
.. toctree::
5+
:maxdepth: 2
6+
7+
introduction
8+
advanced

0 commit comments

Comments
 (0)