During development I make mistakes. And sadly it’s sometimes really hard to figure out what happens under the hood of my app. Often I end up writing statements like echo "<pre>".print_r($var, true)."</pre>";. This works really well in most cases (array’s and simple objects), but when using Doctrine-objects the server will spit out a really long object with lots of recursion.
The new debug dump-tool I now use is a variation on a snippet I found at php.net, I think it was in the comments on the var_dump function. See the image below for my current debug output:
What it prints:
1 - Call-point: which class, which method on what line. Because I code in Symfony I always know which file is associated with which class, otherwise it can easily be added.
2 - What variable/code is evaluated? The dump-tool will analyse the call stack and fetch the original source-line of the call. The source of the call is copied as the default hint. An example: calling wtUtil::dump($this->object); will display as a header: $this->object. wtUtil::dump($this->object['some']['deep']['nested']['array']); will display $this->object['some']['deep']['nested']['array']. It really saves me a lot of extra hinting on what’s being dumped.
3 - It will display (in color) the structure of the (public) attributes of the data
4- In case the variable is an object, it will state the exact class of the object
I hope you write better code than I do, so you don’t have to debug. Otherwise you can use my code for visually debugging your (Doctrine) data-structures. The code is really quick and dirty, but it works. Probably we can improve it a bit and make a plugin together?
<?php /** * */ class wtUtil { //////////////////////////////////////////////////////// // Function: dump // Inspired from: PHP.net Contributions // Description: Helps with php debugging static public function dump($var, $info = FALSE) { $scope = false; $prefix = 'unique'; $suffix = 'value'; if($scope) $vals = $scope; else $vals = $GLOBALS; $old = $var; $var = $new = $prefix.rand().$suffix; $vname = FALSE; foreach($vals as $key => $val) if($val === $new) $vname = $key; $var = $old; echo "<pre style='margin: 0px 0px 10px 0px; display: block; background: white; color: black; font-family: Verdana; border: 1px solid #cccccc; padding: 5px; font-size: 10px; line-height: 13px;'>"; if($info != FALSE) { echo "<b style='color: red;'>$info:</b><br>"; } else { $stack = debug_backtrace(); $caller = $stack[1]; $fileinfo = $stack[0]; echo "in <b style='color: blue;'>$caller[class]$caller[type]$caller[function]</b> on line $fileinfo[line]: "; $code = explode("\n",preg_replace('/\r\n|\r/', "\n", file_get_contents($fileinfo['file']))); $vname = "<b style='color: red; font-size: 125%;'>".htmlspecialchars(preg_replace('/(.*?)dump\((.*?)\);(.*)/i','$2',$code[$fileinfo['line']-1]))."</b>"; } self::do_dump($var, $vname); echo "</"."pre>"; } //////////////////////////////////////////////////////// // Function: do_dump // Inspired from: PHP.net Contributions // Description: Better GI than print_r or var_dump static private function do_dump(&$var, $var_name = NULL, $indent = NULL, $reference = NULL) { $do_dump_indent = "<span style='color:#eeeeee;'>|</span> "; $reference = $reference.$var_name; $keyvar = 'the_do_dump_recursion_protection_scheme'; $keyname = 'referenced_object_name'; if (is_array($var) && isset($var[$keyvar])) { $real_var = &$var[$keyvar]; $real_name = &$var[$keyname]; $type = ucfirst(gettype($real_var)); echo "$indent$var_name <span style='color:#a2a2a2'>$type</span> = <span style='color:#e87800;'>&$real_name</span><br>"; } else { $var = array($keyvar => $var, $keyname => $reference); $avar = &$var[$keyvar]; $type = strtolower(gettype($avar)); if($type == "string") $type_color = "<span style='color:green'>"; elseif($type == "integer") $type_color = "<span style='color:red'>"; elseif($type == "double"){ $type_color = "<span style='color:#0099c5'>"; $type = "float"; } elseif($type == "boolean") $type_color = "<span style='color:#92008d'>"; elseif($type == "null") $type_color = "<span style='color:black'>"; if(is_array($avar)) { $count = count($avar); echo "$indent" . ($var_name ? "$var_name => ":"") . "<span style='color:#a2a2a2'>$type ($count)</span><br>"; if ($count > 0) { echo "$indent(<br>"; $keys = array_keys($avar); foreach($keys as $name) { $value = &$avar[$name]; self::do_dump($value, "['$name']", $indent.$do_dump_indent, $reference); } echo "$indent)<br>"; } } elseif(is_object($avar)) { echo "$indent$var_name <span style='color:#a2a2a2'>is a</span> <b>".get_class($avar)."</b> ("; $newLine = false; foreach($avar as $name=>$value) { if (!$newLine) echo "<br>"; $newLine = true; self::do_dump($value, "$name", $indent.$do_dump_indent, $reference); } echo ($newLine?$indent:"").")<br>"; } elseif(is_int($avar)) echo "$indent$var_name = <span style='color:#a2a2a2'>$type</span> $type_color$avar</span><br>"; elseif(is_string($avar)) echo "$indent$var_name = <span style='color:#a2a2a2'>$type(".strlen($avar).")</span> $type_color\"$avar\"</span><br>"; elseif(is_float($avar)) echo "$indent$var_name = <span style='color:#a2a2a2'>$type</span> $type_color$avar</span><br>"; elseif(is_bool($avar)) echo "$indent$var_name = <span style='color:#a2a2a2'>$type</span> $type_color".($avar == 1 ? "TRUE":"FALSE")."</span><br>"; elseif(is_null($avar)) echo "$indent$var_name = <span style='color:#a2a2a2'>$type</span><br>"; else echo "$indent$var_name = <span style='color:#a2a2a2'>$type(".strlen($avar).")</span> $avar<br>"; $var = $var[$keyvar]; } } }

great thx
one exception : $this->sum = $jobsquery ->select(’sum(TIMETOSEC(duration))/3600 sumduration’) ->from(’Jobs j’) ->fetchOne();
output shows only nulls
hey…
Not sure that this is true) but thanks…
Nice one, I fixed one line to suspend couple notice warnings: echo “in “.@$caller["class"].@$caller["type"].@$caller["function"].” on line “.@$fileinfo["line"].”: “;
There is another lazy way to do it by adding the extension xdebug for PHP, it reduces the output of var_dump to 3 level and do approximatively the same thing as your method (except the color) but without need to include any files or calling any other method.
Absolutly awesome. It will be very useful for sure.