Improved Zend_Debug::dump() and var_dump() functions

The native Zend_Debug::dump() function is a step forward from the usual approach to dumping variables to debug your code (usually by using var_dump or print_r). However, as always, things can be improved and that is what we will try to do in this article.

Those of you who are using Zend framework probably know that Zend_Debug::dump() function is a nice thing when you need to dump your variables in the way var_dump function does it.

Those that are not using Zend framework probably usually do something like this:

  1. print '<pre>';
  2. var_dump($variable);
  3. print '</pre>'; make sure that your output is displayed as a preformatted text on your page rather than as a single line Times New Roman string. This approach is not too bad if do not need to do it too often in which case it soon becomes tiresome.

The goal of the dump function is reduce the amount of code that you need to type as well as to improve the visual look of the output (e.g. align values of arrays and add label/caption).

First, let us look at the code of the function:

  1. <?php
  3. /**
  4.  * Debug helper function.  This is a wrapper for var_dump() that adds
  5.  * the <pre /> tags, cleans up newlines and indents, and runs
  6.  * htmlentities() before output.
  7.  *
  8.  * @param mixed $var     The variable to dump.
  9.  * @param string $label  Label to prepend to output.
  10.  * @param boolean $print Print the output if true.
  11.  * @param boolean $exit  Exit after echoing if true
  12.  * @return string
  13.  */
  14. function dump($var, $label = null, $print = true, $exit = false)
  15. {
  16.     if (defined('APPLICATION_ENV') && (APPLICATION_ENV != 'development')) {
  17.         return $var;
  18.     }
  20.     // format the label
  21.     $label_text = $label;
  22.     $label = ($label === null) ? '' : '<h2 style="margin: 0px">' . trim($label) . '</h2>';
  24.     // var_dump the variable into a buffer and keep the output
  25.     ob_start();
  26.     var_dump($var);
  27.     $output = ob_get_clean();
  29.     // neaten the newlines and indents
  30.     $output = preg_replace("/\]\=\>\n(\s+)/m", "] => ", $output);
  32.     if (is_array($var)) {
  33.         $keys = array_keys_multi($var);
  34.         $maxlen = 0;
  36.         // determine the number of characters in the longest key
  37.         foreach ($keys as $key) {
  38.             $len = strlen($key);
  39.             if ($len > $maxlen) {
  40.                 $maxlen = $len;
  41.             }
  42.         }
  44.         // account for [" and "]
  45.         $maxlen += 4;
  47.         // append spaces between "] and =>
  48.         $output = preg_replace_callback('/\[.*\]/', create_function('$matches', 'return str_pad($matches[0], ' . $maxlen . ');'), $output);
  49.     }
  51.     if (PHP_SAPI == 'cli') {
  52.         $output = PHP_EOL . $label_text
  53.                 . PHP_EOL . $output
  54.                 . PHP_EOL;
  55.     } else {
  56.         if (!extension_loaded('xdebug')) {
  57.             $output = htmlspecialchars($output, ENT_QUOTES);
  58.         }
  60.         $output = '<pre style="font-family: \'Courier New\'; font-size: 11px; background-color: #FBFED7; margin: 5px auto; padding: 10px; border: 1px solid #CCCCCC; max-width: 1000px;">'
  61.                 . $label
  62.                 . $output
  63.                 . '</pre>';
  64.     }
  66.     if ($print === true) {
  67.         print $output;
  68.     }
  70.     if ($exit === true) {
  71.         exit;
  72.     }
  74.     return $output;
  75. }

To those Zend users that have browsed the framework's source it will be pretty obvious that the function is using a lot of code from the original Zend framework library however I have added some useful improvements and removed dependancy from Zend framework.

First of them is checking the application environment. Often you will have different development environments (e.g. development, staging, production, etc.). In those cases you want to make sure that you don't accidentially dump anything in the production environment and that the end user doesn't see it. We all tend to forget to remove some instances of var_dump, print_r and the likes from our code that shouldn't be there.

In this case I chose APPLICATION_ENV as the constant name just because it is the standard environment constant name in Zend framework. However, you can change it to anything you want - replace it with your custom function (e.g. getAppEnvironment()) or simply remove the condition if you want to dump your variables with no regards to the environment.

At the start we call var_dump on $var but capture the output of the function in the buffer rather than print it in our document.

For the next part you will need another one of functions found on, which is called array_keys_multi and can be found in "Extract all keys from a multidimensional array". We will need it to determine the length of the longest key in the array (only if $var is an array).

Just so that you know what array_keys_multi does, let's consider the following example:

  1. $array = array(
  2.     'key1'     => 1,
  3.     'key2'     => 2,
  4.     'subarray' => array(
  5.         'key1' => 3,
  6.     ),
  7. );
  9. $keys = array_keys_multi($array);

In this case array_keys_multi would return 3 items - 'key1', 'key2' and 'subarray'. On lines 34 to 42 we loop through all the keys and determine the length of the longest key, which in our case is 8 - the length of the word 'subarray'.

When we know the number we increase the value of $maxlength variable by 4 because all the key names will be wrapped in [" and "].

Last thing to do is to pad ["keyname"] with spaces so that the following => characters are all aligned to the same position.

Here are examples of how the output would look with and without the formatting:


array(3) {
["key1"] => int(1)
["key2"] => int(2)
["subarray"] => array(1) {
["key1"] => int(3)


array(3) {
["key1"] => int(1)
["key2"] => int(2)
["subarray"] => array(1) {
["key1"] => int(3)

(It might be not that helpful in this example but it becomes such when you start to dump big arrays.)

After the output has been formatted we check if the output source requires html output.

If you are in CLI mode then there is no need to format the output with colors and borders. Therefore we use the original $label_text without any html tags and styling.

If the output is your standard browser then we convert all special characters to their HTML entities (if xdebug module is not enabled) and wrap the output in formatted pre tags.

The rest is self explanatory and depends on $echo and $exit parameters initially passed to the function.

Now about the usage. You can use it in exactly the same way as you use var_dump or print_r. However now you can also define the label (caption) to display above the output, determine if you want to print the output or return, as well as exit right after dumping.

Here is a small example on how to use it:

  1. $array = array(
  2.     'fruits' => array(
  3.         'apples',
  4.         'oranges',
  5.         'bananas',
  6.     ),
  7.     'a_long_key' => 'value_of_the_long_key',
  8.     'a' => array(
  9.         'b' => 'xyz',
  10.     ),
  11. );
  12. $website = '';
  14. dump($array, '$array');
  15. dump($website, '$website');

The output that these dumps would generate will look like this:


array(3) { ["fruits"] => array(3) { [0] => string(6) "apples" [1] => string(7) "oranges" [2] => string(7) "bananas" } ["a_long_key"] => string(21) "value_of_the_long_key" ["a"] => array(1) { ["b"] => string(3) "xyz" } }


string(18) ""

As you can see it looks much better comparing with the usual {php:var-dump} output and is easier to read. Also you only have to type 4 characters to call the function :)

I hope this article helps you develop better and with less effort. Keep up the good work and don't forget to check out other PHP articles!

Zend_Debug adds a bit of sugar, but xdebug extension overload of var_dump() is much more powerful because it can limit the depth of the dump, thus not printing all the linked objects which would result in some megabytes of text. I wrote an article on using it last week and I can share the link here if it is not considered spam.
Giorgio Sironi, August 3rd 2009, 12:25
Sure, go ahead. Any feedback is appreciated!
Andris, August 3rd 2009, 20:22
Email (required)
will not be published
you will only be required to fill it in once in this session

You can use [code][/code] tags in your comments