Improved var_dump() with colored output

As developers, we all do some debugging within the code that we are writing at that moment. Usually the first choice is either calling var_dump or print_r depending on what we are used to but it usually ends the same way:

  1. print '<pre>';
  2. var_dump($something);
  3. // or print_r($something);

Usually the <pre> tag is not even included due to us being lazy and we end up viewing the source because the output that we got in Times New Roman is not really that readable.

Of course, there is Xdebug which we can used but not all of us have control over our webservers or desire to install/enable any extensions.

Here is a class, which you will be able to use in all those occasions.

It could as well be considered an improvement over the class mentioned in one of my previous articles however this class does not change the format of the output, only its colors.

Source code

  1. <?php
  2.  
  3. class Debug
  4. {
  5.  
  6.     /**
  7.      * Dumps information about multiple variables
  8.      *
  9.      * @return void
  10.      */
  11.     public static function dumpMulti()
  12.     {
  13.         // get variables to dump
  14.         $args = func_get_args();
  15.  
  16.         // loop through all items to output
  17.         foreach ($args as $arg) {
  18.             self::dump($arg);
  19.         }
  20.     }
  21.  
  22.  
  23.     /**
  24.      * Dump information about a variable
  25.      *
  26.      * @param mixed $variable Variable to dump
  27.      * @param string $caption Caption of the dump
  28.      * @return void
  29.      */
  30.     public static function dump($variable, $caption = null)
  31.     {
  32.         // don't dump anything in non-development environments
  33.         if (APPLICATION_ENV !== 'development') {
  34.             return;
  35.         }
  36.  
  37.         // prepare the output string
  38.         $html = '';
  39.  
  40.         // start the output buffering
  41.         ob_start();
  42.  
  43.         // generate the output
  44.         var_dump($variable);
  45.  
  46.         // get the output
  47.         $output = ob_get_clean();
  48.  
  49.          $maps = array(
  50.             'string'    => '/(string\((?P<length>\d+)\)) (?P<value>\"(?<!\\\).*\")/i',
  51.             'array'     => '/\[\"(?P<key>.+)\"(?:\:\"(?P<class>[a-z0-9_\\\]+)\")?(?:\:(?P<scope>public|protected|private))?\]=>/Ui',
  52.             'countable' => '/(?P<type>array|int|string)\((?P<count>\d+)\)/',
  53.             'resource'  => '/resource\((?P<count>\d+)\) of type \((?P<class>[a-z0-9_\\\]+)\)/',
  54.             'bool'      => '/bool\((?P<value>true|false)\)/',
  55.             'float'     => '/float\((?P<value>[0-9\.]+)\)/',
  56.             'object'    => '/object\((?P<class>[a-z_\\\]+)\)\#(?P<id>\d+) \((?P<count>\d+)\)/i',
  57.         );
  58.  
  59.         foreach ($maps as $function => $pattern) {
  60.             $output = preg_replace_callback($pattern, array('self', '_process' . ucfirst($function)), $output);
  61.         }
  62.  
  63.         $header = '';
  64.         if (!empty($caption)) {
  65.             $header = '<h2 style="' . self::_getHeaderCss() . '">' . $caption . '</h2>';
  66.         }
  67.  
  68.         print '<pre style="' . self::_getContainerCss() . '">' . $header . $output . '</pre>';
  69.     }
  70.  
  71.  
  72.     /**
  73.      * Process strings
  74.      *
  75.      * @param array $matches Matches from preg_*
  76.      * @return string
  77.      */
  78.     private static function _processString(array $matches)
  79.     {
  80.         $matches['value'] = htmlspecialchars($matches['value']);
  81.         return '<span style="color: #0000FF;">string</span>(<span style="color: #1287DB;">' . $matches['length'] . ')</span> <span style="color: #6B6E6E;">' . $matches['value'] . '</span>';
  82.     }
  83.  
  84.  
  85.     /**
  86.      * Process arrays
  87.      *
  88.      * @param array $matches Matches from preg_*
  89.      * @return string
  90.      */
  91.     private static function _processArray(array $matches)
  92.     {
  93.         // prepare the key name
  94.         $key = '<span style="color: #008000;">"' . $matches['key'] . '"</span>';
  95.         $class = '';
  96.         $scope = '';
  97.  
  98.         // prepare the parent class name
  99.         if (isset($matches['class']) && !empty($matches['class'])) {
  100.             $class = ':<span style="color: #4D5D94;">"' . $matches['class'] . '"</span>';
  101.         }
  102.  
  103.         // prepare the scope indicator
  104.         if (isset($matches['scope']) && !empty($matches['scope'])) {
  105.             $scope = ':<span style="color: #666666;">' . $matches['scope'] . '</span>';
  106.         }
  107.  
  108.         // return the final string
  109.         return '[' . $key . $class . $scope . ']=>';
  110.     }
  111.  
  112.  
  113.     /**
  114.      * Process countables
  115.      *
  116.      * @param array $matches Matches from preg_*
  117.      * @return string
  118.      */
  119.     private static function _processCountable(array $matches)
  120.     {
  121.         $type = '<span style="color: #0000FF;">' . $matches['type'] . '</span>';
  122.         $count = '(<span style="color: #1287DB;">' . $matches['count'] . '</span>)';
  123.  
  124.         return $type . $count;
  125.     }
  126.  
  127.  
  128.     /**
  129.      * Process boolean values
  130.      *
  131.      * @param array $matches Matches from preg_*
  132.      * @return string
  133.      */
  134.     private static function _processBool(array $matches)
  135.     {
  136.         return '<span style="color: #0000FF;">bool</span>(<span style="color: #0000FF;">' . $matches['value'] . '</span>)';
  137.     }
  138.  
  139.  
  140.     /**
  141.      * Process floats
  142.      *
  143.      * @param array $matches Matches from preg_*
  144.      * @return string
  145.      */
  146.     private static function _processFloat(array $matches)
  147.     {
  148.         return '<span style="color: #0000FF;">float</span>(<span style="color: #1287DB;">' . $matches['value'] . '</span>)';
  149.     }
  150.  
  151.  
  152.     /**
  153.      * Process resources
  154.      *
  155.      * @param array $matches Matches from preg_*
  156.      * @return string
  157.      */
  158.     private static function _processResource(array $matches)
  159.     {
  160.         return '<span style="color: #0000FF;">resource</span>(<span style="color: #1287DB;">' . $matches['count'] . '</span>) of type (<span style="color: #4D5D94;">' . $matches['class'] . '</span>)';
  161.     }
  162.  
  163.  
  164.     /**
  165.      * Process objects
  166.      *
  167.      * @param array $matches Matches from preg_*
  168.      * @return string
  169.      */
  170.     private static function _processObject(array $matches)
  171.     {
  172.         return '<span style="color: #0000FF;">object</span>(<span style="color: #4D5D94;">' . $matches['class'] . '</span>)#' . $matches['id'] . ' (<span style="color: #1287DB;">' . $matches['count'] . '</span>)';
  173.     }
  174.  
  175.  
  176.     /**
  177.      * Get the CSS string for the output container
  178.      *
  179.      * @return string
  180.      */
  181.     private static function _getContainerCss()
  182.     {
  183.         return self::_arrayToCss(array(
  184.             'background-color'      => '#d6ffef',
  185.             'border'                => '1px solid #bbb',
  186.             'border-radius'         => '4px',
  187.             '-moz-border-radius'    => '4px',
  188.             '-webkit-border-radius' => '4px',
  189.             'font-size'             => '12px',
  190.             'line-height'           => '1.4em',
  191.             'margin'                => '30px',
  192.             'padding'               => '7px',
  193.         ));
  194.     }
  195.  
  196.  
  197.     /**
  198.      * Get the CSS string for the output header
  199.      *
  200.      * @return string
  201.      */
  202.     private static function _getHeaderCss()
  203.     {
  204.  
  205.         return self::_arrayToCss(array(
  206.             'border-bottom' => '1px solid #bbb',
  207.             'font-size'     => '18px',
  208.             'font-weight'   => 'bold',
  209.             'margin'        => '0 0 10px 0',
  210.             'padding'       => '3px 0 10px 0',
  211.         ));
  212.     }
  213.  
  214.  
  215.     /**
  216.      * Convert a key/value pair array into a CSS string
  217.      *
  218.      * @param array $rules List of rules to process
  219.      * @return string
  220.      */
  221.     private static function _arrayToCss(array $rules)
  222.     {
  223.         $strings = array();
  224.  
  225.         foreach ($rules as $key => $value) {
  226.             $strings[] = $key . ': ' . $value;
  227.         }
  228.  
  229.         return join('; ', $strings);
  230.     }
  231.  
  232. }

As the first most obvious thing - all methods in this class are static simply to avoid the unneccessary instantiation of the class whenever we want to dump something. Many people will probably say that static is the same as global and that it's evil. My opinion is that statism (if there is such a word) is a feature of the language and therefore it can be used whenever needed as long as it's used correctly.

After a quick inspection you will notice that the class contains only two public methods - dump() and dumpMulti().

Debug::dump($variable, $caption = null)

This method allows to dump one specific variable with an optional caption.

Let's generate an example output:

  1. $array = array(
  2.     'integer' => 1234,
  3.     'float' => 12.34,
  4.     'array' => array(
  5.         'a' => 1,  
  6.         'b' => 2,
  7.         'c' => 3,
  8.     ),
  9.     'boolean' => true,
  10.     'resource' => tmpfile(),
  11.     'string' => 'A "string" with 'quotes' and <special[] characters>',
  12.  );
  13.  
  14. Debug::dump($array);

The output for the command above will be:

array(6) {
  ["integer"]=>
  int(1234)
  ["float"]=>
  float(12.34)
  ["array"]=>
  array(3) {
    ["a"]=>
    int(1)
    ["b"]=>
    int(2)
    ["c"]=>
    int(3)
  }
  ["boolean"]=>
  bool(true)
  ["resource"]=>
  resource(94) of type (stream)
  ["string"]=>
  string(51) "A "string" with 'quotes' and <special[] characters>" 
}

As you can see, the output is pretty similar to what xdebug would output.

Debug::dumpMulti($var1, $var2, $var3, ...)

This function is simply a wrapper for dump() allowing you to pass multiple variables to dump. That means you can do

  1. Debug::dump($_GET, $_POST, $_SERVER, $_COOKIES);

instead of

  1. Debug::dump($_GET);
  2. Debug::dump($_POST);
  3. Debug::dump($_SERVER);
  4. Debug::dump($_COOKIES);

The only drawback of using the multi version is that it doesn't allow you to define captions, which are useful if you are outputting variables from within a loop or from multiple places in your code.

Styling

I wouldn't be surprised if you don't really fancy the default colors that are pre-set in the class. We all have our preferences to how the code should look and this is most probably not an exception.

Changing the default colors is very simple. All you need to do is modify the array defined in _getContainerCss(). It is a key/value pair array of CSS rules. Change that to your liking and voila!

The same thing applies to the header, except in this case you have to change contents of the array in _getHeaderCss().

-

As always - I hope this helps you with your development process and makes it a tad easier to debug stuff.

Comments
1
Very helpful... added a third boolean parameter that does a die() after dump to kill further script execution.
gavin, February 18th 2012, 11:49
2
To use when you debug your site add :
define("APPLICATION_ENV", "development");

Regards
Pierre BLONDEAU, March 7th 2013, 14:42
3
Just wanted to say thanks... I use this in all my code now for debugging... it makes it 10x easier to see whats going on... I noticed the HTML layout was a bit funky so I made some major improvements to it and the colors as well... If your interested in seeing it and maybe updating yours let me know... I think it adds significant benefit to the class... in any case... thanks again... this is an awesome addition to my tools collection.
Kevin, August 8th 2013, 0:57
4
Hi Kevin! Thanks and I'm glad it was of use to you! :)

Feel free to paste a link to your updated version (pastebin or similar) here. I don't mind external links.
Andris, August 12th 2013, 20:33
Name
Email (required)
will not be published
Website
Recaptcha
you will only be required to fill it in once in this session

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