diff --git a/components/index.rst b/components/index.rst index 8e167cd2ac9..6386caab5df 100644 --- a/components/index.rst +++ b/components/index.rst @@ -29,6 +29,7 @@ The Components stopwatch templating/index translation/index + var_dumper/index yaml/index .. include:: /components/map.rst.inc diff --git a/components/map.rst.inc b/components/map.rst.inc index f9eab711e07..93797c2e5d3 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -143,6 +143,11 @@ * :doc:`/components/translation/usage` * :doc:`/components/translation/custom_formats` +* :doc:`/components/var_dumper/index` + + * :doc:`/components/var_dumper/introduction` + * :doc:`/components/var_dumper/advanced` + * :doc:`/components/yaml/index` * :doc:`/components/yaml/introduction` diff --git a/components/var_dumper/advanced.rst b/components/var_dumper/advanced.rst new file mode 100644 index 00000000000..9b70c8fdfd4 --- /dev/null +++ b/components/var_dumper/advanced.rst @@ -0,0 +1,205 @@ +.. index:: + single: VarDumper + single: Components; VarDumper + +Advanced Usage of the VarDumper Component +========================================= + +``dump()`` function is just a thin wrapper and a more convenient way to call +:method:`VarDumper::dump() `. +You can change the behavior of this function by calling +:method:`VarDumper::setHandler($callable) `: +calls to ``dump()`` will then be forwarded to ``$callable``. + +Cloners +~~~~~~~ + +A cloner is used to create an intermediate representation of any PHP variable. +Its output is a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` +object that wraps this representation. + +You can create a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` +object this way:: + + $cloner = new VarCloner(); + $data = $cloner->cloneVar($myVar); + +A cloner also applies limits when creating this representation, so that the +corresponding Data object could represent only a subset of the cloned variable. +Before :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::cloneVar`, +you can configure these limits: + +* :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::setMaxItems` + configures the maximum number of items that will be cloned *past the first + nesting level*. Items are counted using a breadth-first algorithm so that + lower level items have higher priority than deeply nested items; +* :method:`Symfony\\Component\\VarDumper\\Cloner\\VarCloner::setMaxString` + configures the maximum number of characters that will be cloned before + cutting overlong strings; +* in both cases, specifying `-1` removes any limit. + +Before dumping it, you can further limit the resulting +:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object by calling its +:method:`Symfony\\Component\\VarDumper\\Cloner\\Data::getLimitedClone` +method: + +* the first ``$maxDepth`` argument allows limiting dumps in the depth dimension, +* the second ``$maxItemsPerDepth`` limits the number of items per depth level, +* and the last ``$useRefHandles`` defaults to ``true`` but allows removing + internal objects' handles for sparser output, +* but unlike the previous limits on cloners that remove data on purpose, + these can be changed back and forth before dumping since they do not affect + the intermediate representation internally. + +.. note:: + + When no limit is applied, a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` + object is as accurate as the native :phpfunction:`serialize` function + and thus could have a wider purpose than strictly dumping for debugging. + +Dumpers +~~~~~~~ + +A dumper is responsible for outputting a string representation of a PHP variable, +using a :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object as input. +The destination and the formatting of this output vary with dumpers. + +This component comes with an :class:`Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper` +for HTML output and a :class:`Symfony\\Component\\VarDumper\\Dumper\\CliDumper` +for optionally colored command line output. + +For example, if you want to dump some ``$variable``, just do:: + + $cloner = new VarCloner(); + $dumper = new CliDumper(); + + $dumper->dump($cloner->cloneVar($variable)); + +By using the first argument of the constructor, you can select the output +stream where the dump will be written. By default, the ``CliDumper`` writes +on ``php://stdout`` and the ``HtmlDumper`` on ``php://output``, but any PHP +stream (resource or URL) is acceptable. + +Instead of a stream destination, you can also pass it a ``callable`` that +will be called repeatedly for each line generated by a dumper. This +callable can be configured using the first argument of a dumper's constructor, +but also using the +:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::setOutput` +method or the second argument of the +:method:`Symfony\\Component\\VarDumper\\Dumper\\AbstractDumper::dump` method. + +For example, to get a dump as a string in a variable, you can do:: + + $cloner = new VarCloner(); + $dumper = new CliDumper(); + $output = ''; + + $dumper->dump( + $cloner->cloneVar($variable), + function ($line, $depth) use (&$output) { + // A negative depth means "end of dump" + if ($depth >= 0) { + // Adds a two spaces indentation to the line + $output .= str_repeat(' ', $depth).$line."\n"; + } + } + ); + + // $output is now populated with the dump representation of $variable + +An other option for doing the same could be:: + + cloner = new VarCloner(); + $dumper = new CliDumper(); + $output = fopen('php://memory', 'r+b'); + + $dumper->dump($cloner->cloneVar($variable), $output); + rewind($output); + $output = stream_get_contents($output); + + // $output is now populated with the dump representation of $variable + +Dumpers implement the :class:`Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface` +interface that specifies the +:method:`dump(Data $data) ` +method. They also typically implement the +:class:`Symfony\\Component\\VarDumper\\Cloner\\DumperInterface` that frees +them from re-implementing the logic required to walk through a +:class:`Symfony\\Component\\VarDumper\\Cloner\\Data` object's internal structure. + +Casters +~~~~~~~ + +Objects and resources nested in a PHP variable are casted to arrays in the +intermediate :class:`Symfony\\Component\\VarDumper\\Cloner\\Data` +representation. You can tweak the array representation for each object/resource +by hooking a Caster into this process. The component already includes many +casters for base PHP classes and other common classes. + +If you want to build your own Caster, you can register one before cloning +a PHP variable. Casters are registered using either a Cloner's constructor +or its ``addCasters()`` method:: + + $myCasters = array(...); + $cloner = new VarCloner($myCasters); + + // or + + $cloner->addCasters($myCasters); + +The provided ``$myCasters`` argument is an array that maps a class, +an interface or a resource type to a callable:: + + $myCasters = array( + 'FooClass' => $myFooClassCallableCaster, + ':bar resource' => $myBarResourceCallableCaster, + ); + +As you can notice, resource types are prefixed by a ``:`` to prevent +colliding with a class name. + +Because an object has one main class and potentially many parent classes +or interfaces, many casters can be applied to one object. In this case, +casters are called one after the other, starting from casters bound to the +interfaces, the parents classes and then the main class. Several casters +can also be registered for the same resource type/class/interface. +They are called in registration order. + +Casters are responsible for returning the properties of the object or resource +being cloned in an array. They are callables that accept four arguments: + +* the object or resource being casted, +* an array modelled for objects after PHP's native ``(array)`` cast operator, +* a :class:`Symfony\\Component\\VarDumper\\Cloner\\Stub` object + representing the main properties of the object (class, type, etc.), +* true/false when the caster is called nested is a structure or not. + +Here is a simple caster not doing anything:: + + function myCaster($object, $array, $stub, $isNested) + { + // ... populate/alter $array to your needs + + return $array; + } + +For objects, the ``$array`` parameter comes pre-populated using PHP's native +``(array)`` casting operator or with the return value of ``$object->__debugInfo()`` +if the magic method exists. Then, the return value of one Caster is given +as argument to the next Caster in the chain. + +When casting with the ``(array)`` operator, PHP prefixes protected properties +with a ``\0*\0`` and private ones with the class owning the property: +e.g. ``\0Foobar\0`` prefixes all private properties of objects of type Foobar. +Casters follow this convention and add two more prefixes: ``\0~\0`` is used +for virtual properties and ``\0+\0`` for dynamic ones (runtime added +properties not in the class declaration). + +.. note:: + + Although you can, it is best advised not to alter the state of an object + while casting it in a Caster. + +.. tip:: + + Before writting your own casters, you should check the existing ones. diff --git a/components/var_dumper/index.rst b/components/var_dumper/index.rst new file mode 100644 index 00000000000..2c67f2aa53f --- /dev/null +++ b/components/var_dumper/index.rst @@ -0,0 +1,8 @@ +VarDumper +========= + +.. toctree:: + :maxdepth: 2 + + introduction + advanced diff --git a/components/var_dumper/introduction.rst b/components/var_dumper/introduction.rst new file mode 100644 index 00000000000..6f43b67ef3d --- /dev/null +++ b/components/var_dumper/introduction.rst @@ -0,0 +1,211 @@ +.. index:: + single: VarDumper + single: Components; VarDumper + +The VarDumper Component +======================= + + The VarDumper component provides mechanisms for walking through any + arbitrary PHP variable. Built on top, it provides a better ``dump()`` + function that you can use instead of :phpfunction:`var_dump`. + +.. versionadded:: 2.6 + The VarDumper component was introduced in Symfony 2.6. + +Installation +------------ + +You can install the component in 2 different ways: + +* :doc:`Install it via Composer ` (``symfony/var-dumper`` on `Packagist`_); +* Use the official Git repository (https://github.com/symfony/var-dumper). + +The dump() Function +------------------- + +The VarDumper component creates a global ``dump()`` function that you can +use instead of e.g. :phpfunction:`var_dump`. By using it, you'll gain: + +* Per object and resource types specialized view to e.g. filter out + Doctrine internals while dumping a single proxy entity, or get more + insight on opened files with :phpfunction:`stream_get_meta_data`; +* Configurable output formats: HTML or colored command line output; +* Ability to dump internal references, either soft ones (objects or + resources) or hard ones (``=&`` on arrays or objects properties). + Repeated occurrences of the same object/array/resource won't appear + again and again anymore. Moreover, you'll be able to inspect the + reference structure of your data; +* Ability to operate in the context of an output buffering handler. + +By default, the output format and destination are selected based on your +current PHP SAPI: + +* On the command line (CLI SAPI), the output is written on ``STDOUT``. This + can be surprising to some because this bypasses PHP's output buffering + mechanism; +* On other SAPIs, dumps are written as HTML on the regular output. + +.. note:: + + If you want to catch the dump output as a string, please read the + `advanced documentation `_ which contains examples of it. + You'll also learn how to change the format or redirect the output to + wherever you want. + +DebugBundle and Twig Integration +-------------------------------- + +The ``DebugBundle`` allows greater integration of the component into the +Symfony full stack framework. It is enabled by default in the *dev* and *test* +environement of the standard edition since version 2.6. + +Since generating (even debug) output in the controller or in the model +of your application may just break it by e.g. sending HTTP headers or +corrupting your view, the bundle configures the ``dump()`` function so that +variables are dumped in the web debug toolbar. + +But if the toolbar can not be displayed because you e.g. called ``die``/``exit`` +or a fatal error occurred, then dumps are written on the regular output. + +In a Twig template, two constructs are available for dumping a variable. +Choosing between both is mostly a matter of personal taste, still: + +* ``{% dump foo.bar %}`` is the way to go when the original template output + shall not be modified: variables are not dumped inline, but in the web + debug toolbar; +* on the contrary, ``{{ dump(foo.bar) }}`` dumps inline and thus may or not + be suited to your use case (e.g. you shouldn't use it in an HTML + attribute or a ``