Skip to content

Instantly share code, notes, and snippets.

@peterjwest
Last active August 26, 2023 23:29
Show Gist options
  • Save peterjwest/5459304 to your computer and use it in GitHub Desktop.
Save peterjwest/5459304 to your computer and use it in GitHub Desktop.
var_dump() sucks

Better variable dumping for PHP

  • debug($variable) prints html and source code friendly variable information
  • inspect($variable) returns the variable information as a string

Associative arrays are printed as:

{
  key: 'value'
  'key 2': 'value 2'
}

Numeric arrays:

[
    'value 1',
    'value 2',
    'value 3'
]

Objects:

Name\Space\Foo#0 (
    attribute: 'value',
    *privateAttribute: 'value'
)

The asterisk before privateAttribute signifies that this attribute is private. The #0 after the class signifies the instance of the class, if this instance occurs again, its contents won't be printed to prevent recursion e.g.

$x = new Foo;
$y = new Bar;
$x->self = $x;
$x->other = $y;
$y->self = $y;
$y->other = $x;
debug($x);

Outputs:

Foo#0 (
  self: Foo#0,
  other: Bar#0 (
    self: Bar#0,
    other: Foo#0 
  )
)

Set the max depth to dump only shallow data:

$x = new Foo;
$x->bar = array(1, 2, 3);
$array = array('foo' => $x);
debug($array, 2);

Outputs:

{
    foo: Foo#0: (
        bar: [
            ...
        ]
    )
}
<?php
// Outputs debug info for a variable
function debug($var, $maxDepth = 6, $referenceMap = array(), $depth = 1) {
echo '<pre>' . inspect($var, $maxDepth, $referenceMap, $depth) . '</pre>';
}
// Returns debug info for a variable
function inspect($var, $maxDepth = 6, &$referenceMap = array(), $depth = 1) {
if (is_array($var)) return inspect_contents($var, $maxDepth, $referenceMap, $depth);
if (is_object($var)) return inspect_object($var, $maxDepth, $referenceMap, $depth);
if (is_resource($var)) return 'Resource#(' . get_resource_type($var) . ')';
return var_export($var, true);
}
// Returns debug info for an object,
// $referenceMap prevents repeated objects from being listed recursively
function inspect_object($obj, $maxDepth = 6, &$referenceMap = array(), $depth = 0) {
$class = get_class($obj);
$hash = spl_object_hash($obj);
$contents = '';
// We create a sub array for each class
if (!isset($referenceMap[$class])) $referenceMap[$class] = array();
// We use the object hash to track each instance of the class
if (!isset($referenceMap[$class][$hash])) {
$referenceMap[$class][$hash] = count($referenceMap[$class]);
$contents = ' ' . inspect_contents($obj, $maxDepth, $referenceMap, $depth);
}
return '' . $class . "#". $referenceMap[$class][$hash] . $contents;
}
// Returns debug info for the contents of an object or array
function inspect_contents($var, $maxDepth = 6, &$referenceMap = array(), $depth = 0) {
if ($maxDepth !== null && $depth >= $maxDepth) {
$contents = str_repeat(' ', $depth + 1) . '...';
}
else {
$values = array();
// We show the keys to each value if its not a numeric array
$showKeys = is_object($var) || is_associative($var);
foreach ((array) $var as $key => $val) {
// Addresses PHP's strange behavior for private/protected properties when array casting objs:
if (is_object($var)) $key = preg_replace('~^\0[^\0]*\0~', '*', $key);
// Quote the key if it has spaces
if (strpos($key, ' ') !== false) $key = "'$key'";
// Forms the output of each value
$key = $showKeys ? "$key: " : '';
$indent = str_repeat(' ', $depth + 1);
$values[] = $indent . $key . inspect($val, $maxDepth, $referenceMap, $depth + 1);
}
$contents = implode(",\n", $values);
}
// Delimiters are selected by the variable type
$delimiters = array('[', ']');
if (is_object($var)) $delimiters = array('(', ')');
else if (is_associative($var)) $delimiters = array('{', '}');
return $delimiters[0] . "\n" . $contents . "\n" . str_repeat(' ', $depth) . $delimiters[1];
}
// Returns if an array has numeric keys only
function is_associative($array) {
return array_keys($array) !== range(0, count($array) - 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment