Debug - Amélioration de print_r()

Mammouth du PHP | 983 Messages

08 janv. 2006, 22:15

Pour celles et ceux, qui comme moi, n'utilisent pas d'outils pour debuguer comme XDebug ou DBG, voici une amélioration pratique de print_r():

Source et résultat : http://www.tatane.com/index.php/print_rn
function print_rn($data) {
    ob_start();
    var_dump($data);
    $c = ob_get_contents();
    ob_end_clean();
 
    $c = preg_replace("/\r\n|\r/", "\n", $c);
    $c = str_replace("]=>\n", '] = ', $c);
    $c = preg_replace('/= {2,}/', '= ', $c);
    $c = preg_replace("/\[\"(.*?)\"\] = /i", "[$1] = ", $c);
    $c = preg_replace('/    /', "        ", $c);
    $c = preg_replace("/\"\"(.*?)\"/i", "\"$1\"", $c);
 
    $c = htmlspecialchars($c, ENT_NOQUOTES);
 
    // Expand numbers (ie. int(2) 10 => int(1) 2 10, float(6) 128.64 => float(1) 6 128.64 etc.)
    $c = preg_replace("/(int|float)\(([0-9\.]+)\)/ie", "'$1('.strlen('$2').') <span class=\"number\">$2</span>'", $c);
    
    // Syntax Highlighting of Strings. This seems cryptic, but it will also allow non-terminated strings to get parsed.
    $c = preg_replace("/(\[[\w ]+\] = string\([0-9]+\) )\"(.*?)/sim", "$1<span class=\"string\">\"", $c);
    $c = preg_replace("/(\"\n{1,})( {0,}\})/sim", "$1</span>$2", $c);
    $c = preg_replace("/(\"\n{1,})( {0,}\[)/sim", "$1</span>$2", $c);
    $c = preg_replace("/(string\([0-9]+\) )\"(.*?)\"\n/sim", "$1<span class=\"string\">\"$2\"</span>\n", $c);
    
    $regex = array(
            // Numberrs
            'numbers' => array('/(^|] = )(array|float|int|string|resource|object\(.*\)|\&object\(.*\))\(([0-9\.]+)\)/i', '$1$2(<span class="number">$3</span>)'),
            
            // Keywords
            'null' => array('/(^|] = )(null)/i', '$1<span class="keyword">$2</span>'),
            'bool' => array('/(bool)\((true|false)\)/i', '$1(<span class="keyword">$2</span>)'),
            
            // Types
            'types' => array('/(of type )\((.*)\)/i', '$1(<span class="type">$2</span>)'),
            
            // Objects
            'object' => array('/(object|\&object)\(([\w]+)\)/i', '$1(<span class="object">$2</span>)'),
            
            // Function
            'function' => array('/(^|] = )(array|string|int|float|bool|resource|object|\&object)\(/i', '$1<span class="function">$2</span>('),
    );
    
    foreach ($regex as $x) {
            $c = preg_replace($x[0], $x[1], $c);
    }
    
    $style = '
    /* outside div - it will float and match the screen */
    .dumpr {
            margin: 2px;
            padding: 2px;
            background-color: #fbfbfb;
            float: left;
            clear: both;
    }
    /* font size and family */
    .dumpr pre {
            color: #000000;
            font-size: 9pt;
            font-family: "Courier New",Courier,Monaco,monospace;
            margin: 0px;
            padding-top: 5px;
            padding-bottom: 7px;
            padding-left: 9px;
            padding-right: 9px;
    }
    /* inside div */
    .dumpr div {
            background-color: #fcfcfc;
            border: 1px solid #d9d9d9;
            float: left;
            clear: both;
    }
    /* syntax highlighting */
    .dumpr span.string {color: #c40000;}
    .dumpr span.number {color: #ff0000;}
    .dumpr span.keyword {color: #007200;}
    .dumpr span.function {color: #0000c4;}
    .dumpr span.object {color: #ac00ac;}
    .dumpr span.type {color: #0072c4;} 
    .legenddumpr {
   		background-color: #fcfcfc;
        border: 1px solid #d9d9d9;
        padding: 2px;           
    }        
    ';
    
    $style = preg_replace("/ {2,}/", "", $style);
    $style = preg_replace("/\t|\r\n|\r|\n/", "", $style);
    $style = preg_replace("/\/\*.*?\*\//i", '', $style);
    $style = str_replace('}', '} ', $style);
    $style = str_replace(' {', '{', $style);
    $style = trim($style);
 
    $c = trim($c);
    $c = preg_replace("/\n<\/span>/", "</span>\n", $c);
    
    echo "<style type=\"text/css\">".$style."</style>\n";
	echo '<fieldset class="dumpr">';
		echo '<legend class="legenddumpr">'.basename($_SERVER['SCRIPT_FILENAME']).'</legend>';
		//echo '<div>';
			echo '<pre>'.$c.'</pre>';
		//echo '</div>';
		
	echo '</fieldset>';
    echo "<div style=\"clear:both;\">&nbsp;</div>";
}
Une fois testée, on a du mal à s'en passer ;)

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

09 janv. 2006, 02:19

Pour débugger je n'utilise pas print_r mais var_dump. Cette fonction a d'ailleurs le même affichage que print_rn sauf qu'il n'y a pas besoin de réinventer la roue ;)

Mammouth du PHP | 983 Messages

09 janv. 2006, 10:33

Cette fonction renvoit le resultat de var_dump(), mais avec un affichage plus sympa. C'est pas une façon de réinventer la roue mais simplement avoir un peu plus de comfort. ;)

ViPHP
ViPHP | 1380 Messages

09 janv. 2006, 15:47

Si tu veux indenter et mettre en page un array, il vaut mieux utiliser les listes HTML. Elles sont faites pour ça. Tu règles les marges et puces comme tu le veux (css).

Voici ce que j'utilise pour afficher un tableau dans une page qui doit être conforme aux recommandations des petits gras du W3C:
/********************************************************************************************
AFFICHAGE ARRAY - récursive xhtml compatible
 arg1 array uni ou multi
*********************************************************************************************/

function print_tab($tab){
  if (!is_array($tab)) return false;
  static $balise_fermante = array();
  $str = "<ul>\r\n";
  $balise_fermante[] = "</ul>\r\n";
  foreach ($tab as $k=>$v){
    if(is_array($v)){
      $str .= "<li>[$k]=> array\r\n";
      $balise_fermante[] = "</li>\r\n";
      $str .= print_tab($v);
    }else{
      $str .= "<li>[$k]=>".htmlentities($v);
      $balise_fermante[] = "</li>\r\n";
    }
    $str .= array_pop($balise_fermante);
  }
  $str .= array_pop($balise_fermante);
  return $str;
}

$t = array('a', 'b', array(1,2,'clé'=>3,5,array('AZERTY', 'QWERTY'),778,58), 'Fin');

echo print_tab($t);
Si tu cherches quelque chose de basique (non conforme car les balises html ne sont pas fermées dans le bon ordre). Même idée de récursivité:
function aff_tab($tab){
  echo "<ul>\r\n";
  foreach($tab AS $k => $val){    
    if( !is_array($val)){
      echo "<li>[$k]=>".htmlentities($val)."</li>\r\n";
    }else{
      echo "<li>[$k]=> </li>\r\n";
      aff_tab($val);
    }
  }
  echo "</ul>\r\n";
}

print_tab($t);
Un peu moins lourd et tout aussi beau à l'affichage. :wink:
ripat

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

09 janv. 2006, 17:16

Pour ce qui est du debuggage, j'encadre souvent mes print_r par des balises <pre></pre> qui affichent le texte tel qu'il formaté dans le code HTML. Je trouve que c'est moins lourd que de parser le retour de print_r.

J'ai donc créé cette petite fonction qui encadre print_r par ces balises et qui contient 2 arguments facultatifs permettant d'insérer du code HTML avant et après les balise <PRE>

Je les utilise par exemple pour mettre une balise <hr /> avant et après le tableau afin de bien le repérer
/*	DESCRIPTION : permet d'afficher le contenu d'un tableau avec la fonction print_r en l'encadrant avec les balises <PRE>
	>>	afin qu'elle soit lisible dans le navigateur
	PRE :	$array contient le tableau à afficher
			$before contient le texte HTML à afficher avant le tableau - FACULTATIF
			$after contient le texte HTML à afficher après le tableau - FACULTATIF
*/
function print_tab($array, $before = "", $after = "") {
	//Affichage du texte HTML avant le tableau
	echo $before."\n";
	//Encadrement de l'affichage du tableau par des balises <PRE>
	echo "<pre>\n";
	//Affichage récursif du tableau
	print_r($array);
	echo "</pre>\n";
	//Affichage du texte HTML après le tableau
	echo $after."\n";
}
exemple d'appel
$a_statut = array("Admin", "Modérateur", "ViPHP", "Membre", "Invité");

echo "Debugage de mon tableau:<br />\n";
print_tab($a_statut, "<hr />", "<hr />");
echo "Fin du debugage<br />\n";
Résultat obtenu
Image
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer