The Greatest PHP Debugging Function of All Time
December 22nd, 2009 Posted in Techie
I normally try to keep the tech stuff to a minimum on the blog, but this function is in high demand from anyone who’s ever had it and then worked on another codebase without it. Simple, but mind-blowingly useful. Without further ado, I present, YO.
NOTE: This is a re-write of some code I wrote at Yahoo!, so I wanted to give credit to the two folks who had a hand in the debugging system we built there, from which this is derived: Chris and Sara.
You’re welcome, America.
<?php /** * The greatest debugging class in history. Here's why: * * - outputs to both the error log and optionally the screen. * - formats output nicely so you can see your debugging output * - shows you where the yo() call is IN THE OUTPUT so if you * leave a yo() in someplace, you can track it down easy-peasy. * - accepts multiple args just like var_dump * - feel free to use the sub functions too (like var_dump_str) * * @author Jacob Rosenberg <themasterof@rightuptop.com> * @author Sara Golemon * @author Chris Draycott * */ class Yo { /* {{{ */ /** * getCallerLine * * gets the calling line of the function it was called from, * i.e., this function's grandparent. * * @returns string Name of calling function */ static public function getCallerLine($levels = 2) { $bt = debug_backtrace(); $file = isset($bt[$levels]['file']) ? $bt[$levels]['file'] : ''; $line = isset($bt[$levels]['line']) ? $bt[$levels]['line'] : ''; return array($file, $line); } /* }}} */ /* {{{ */ /** * getCaller * * gets the calling function of the function it was called from, * i.e., this function's grandparent. * * @returns string Name of calling function */ static public function getCaller($levels = 2) { $bt = debug_backtrace(); if (isset($bt[$levels])) { $caller = $bt[$levels]['function']; if (isset($bt[$levels]['class'])) { $caller = $bt[$levels]['class'] . "::" . $caller; } } else { $caller = 'main'; } return $caller; } /* {{{ */ /** * var_dump_str * * var_dump, but with returned output. * OB capture is gross, but print_r($x,1) sucks compared to var_dump. * * @param mixed PHP Variable to be var_dump'd * @returns string var_dump representation of that variable */ function var_dump_str($var) { ob_start(); var_dump($var); $out = ob_get_contents(); ob_end_clean(); return $out; } /* }}} */ /** * isInternal * * determines if a user is an internal user. * * @return bool true if the user is internal and should see debug output */ public static function isInternal() { // feel free to add some code here that // turns on debug output for only a subset of users. // return true; } /* }}} */ /* {{{ */ /** * yo - figure it out yourself, dummy * * @param mixed Variable(s) to be dumped (var args) * ... */ public static function do_yo() { $internal = self::isInternal(); $caller = self::getCaller(); if ($internal) { echo "<pre><h1>YO!!: $caller</h1>"; } error_log("YO!!:: $caller"); foreach (func_get_args() as $var) { $output = ($var === false) ? 'bool(false)' : Yo::var_dump_str($var); if ($internal) { echo htmlentities($output, ENT_QUOTES, 'UTF-8') . "\n"; } error_log($output); } if ($internal) echo "</pre>"; } /* }}} */ /* {{{ */ /** * yo_bt - figure it out yourself, dummy * */ public static function do_yo_bt() { $internal = self::isInternal(); $caller = self::getCaller(); if ($internal) { echo "<pre><h1>YO bt!!: $caller</h1>"; } error_log("YO bt!!:: $caller"); $bt = debug_backtrace(); foreach ($bt as $line) { if ($internal) echo $line['function'] . "\n"; error_log($line['function']); } if ($internal) echo "</pre>"; } /* }}} */ } /* }}} */ // shortcuts! ------ function yo() { return Yo::do_yo(); } function yo_bt() { return Yo::do_yo_bt(); }
No related posts.