Visually debugging Doctrine

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:

Sample 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> &nbsp;&nbsp; ";
      $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;'>&amp;$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];
      }
  }
}

5 Responses to “Visually debugging Doctrine”

  1. matze123 says:

    great thx

    one exception : $this->sum = $jobsquery ->select(’sum(TIMETOSEC(duration))/3600 sumduration’) ->from(’Jobs j’) ->fetchOne();

    output shows only nulls

  2. hey…

    Not sure that this is true) but thanks…

  3. Anton says:

    Nice one, I fixed one line to suspend couple notice warnings: echo “in “.@$caller["class"].@$caller["type"].@$caller["function"].” on line “.@$fileinfo["line"].”: “;

  4. Damien says:

    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.

  5. Mike says:

    Absolutly awesome. It will be very useful for sure.

Leave a Reply