1. Einleitung
Für Debugging-Zwecke sind Funktionen nützlich, die jede beliebige Variable ausgeben können (idealerweise inklusive Datentyp). Standardmäßig werden von PHP drei solcher Funktionen zur Verfügung gestellt: var_dump(), print_r() und var_export(). Die Ausgaben dieser Funktionen sind sehr ähnlich. var_dump() ist speziell für Debugging-Zwecke gedacht und stellt daher genaue Informationen zu allen Datentypen dar. print_r() soll die Variablen „lesbar” darstellen und ergänzt daher in der Regel keine Datentypen. var_export() dient — dem Namen nach — zum Exportieren von Variablen, sodass der sich ergebende String wiederum per eval() ausgeführt werden kann, um die selbe Variable erneut zu erzeugen.
Der Nutzen von print_r() ist eher gering, da für Debugging-Zwecke die Datentypen zu wichtig sind als dass man auf sie verzichten kann. Bei Ausgaben, die sich an den Besucher richten, sollten wiederum die Datentypen der auszugebenden Variablen bekannt sein, sodass print_r() nicht notwendig ist. Das Exportieren von Variablen mittels var_export() wird nur sehr selten benötigt. So bleibt var_dump() als empfehlenswerte Methode zur Ausgabe von Variablen übrig.
2. var_dump()
Einige beispielhafte Ausgaben von var_dump():
<?php var_dump((int)1000); var_dump((float)1.3144345); var_dump((bool)false); var_dump((string)"test"); var_dump((object)new stdClass()); var_dump((unset)null); var_dump((array)array(1, 2, 3)); ?>
int(1000) float(1.3144345) bool(false) string(4) "test" object(stdClass)#1 (0) { } NULL array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
var_dump() verhält sich wie echo: Alles was man an die Funktion übergibt wird sofort ausgegeben. Um das zu verhindern kann das Output Buffering verwendet werden. Mit ob_start() wird dies aktiviert — Ausgaben werden dann nicht mehr sofort an den Besucher gesendet. Über ob_get_contents() kann der bisherige Inhalt des Buffers abgefragt werden, um diesen in eine Variable zu übertragen. Beendet wird das Output Buffering wiederum mit ob_end_clean(). Die nachfolgende Funktion „myVarDump()” verwendet diese Technik, um die Ausgabe von var_dump „abzufangen” und per return zurückzugeben.
<?php function myVarDump($var) { ob_start(); var_dump($var); $out = ob_get_contents(); ob_end_clean(); return $out; } echo myVarDump((int)1000); echo myVarDump((float)1.42342); echo myVarDump(null); ?>
int(1000) float(1.42342) NULL
Um sämtliche definierte Variablen zu sehen kann die Funktion get_defined_vars() zur Hilfe genommen werden. Diese gibt ein Array zurück, welches alle Variablen enthält (Name der Variable als Schlüssel, Inhalt der Variable als Wert, der dem Schlüssel zugeordnet ist).
<?php $a = 1343; $b = "example"; $c = array(10, 11, 12); $d = array(array(array("test"))); $e = false; var_dump(get_defined_vars()); ?>
array(10) { ["GLOBALS"]=> &array(10) { ["GLOBALS"]=> *RECURSION* ["_POST"]=> array(0) { } ["_GET"]=> array(0) { } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["a"]=> int(1343) ["b"]=> string(7) "example" ["c"]=> array(3) { [0]=> int(10) [1]=> int(11) [2]=> int(12) } ["d"]=> array(1) { [0]=> array(1) { [0]=> array(1) { [0]=> string(4) "test" } } } ["e"]=> bool(false) } ["_POST"]=> array(0) { } ["_GET"]=> array(0) { } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["a"]=> int(1343) ["b"]=> string(7) "example" ["c"]=> array(3) { [0]=> int(10) [1]=> int(11) [2]=> int(12) } ["d"]=> array(1) { [0]=> array(1) { [0]=> array(1) { [0]=> string(4) "test" } } } ["e"]=> bool(false) }
Die vorherige Ausgabe ist sehr umfangreich und enthält etwa auch alle globalen Variablen. Das von get_defined_vars() zurückgegebene Array kann daher „zurechtgestutzt” werden indem man array_diff_keys() verwendet. Mit array_diff_keys($arr1, $arr2) lassen sich aus $arr1 alle Schlüssel entfernen, die auch zugleich Schlüssel in $arr2 sind.
<?php $a = 1343; $b = "example"; $c = array(10, 11, 12); $d = array(array(array("test"))); $e = false; var_dump( array_diff_key( // erzeuge get_defined_vars() ... get_defined_vars(), // ... ohne die folgenden Schluessel: array_flip(array('GLOBALS', '_POST', '_FILES', '_COOKIE')) ) ); ?>
array(6) { ["_GET"]=> array(0) { } ["a"]=> int(1343) ["b"]=> string(7) "example" ["c"]=> array(3) { [0]=> int(10) [1]=> int(11) [2]=> int(12) } ["d"]=> array(1) { [0]=> array(1) { [0]=> array(1) { [0]=> string(4) "test" } } } ["e"]=> bool(false) }
3. print_r()
Das nächste Beispiel zeigt die Ausgaben von print_r(). Man beachte dabei, dass die Datentypen in der Regel nicht Teil der Ausgabe sind. Im Gegensatz zu var_dump() erzeugt print_r() zudem nicht immer einen Zeilenumbruch am Ende der Ausgabe, sodass dieser manuell hinzugefügt werden muss.
<?php print_r((int)1000); echo("\n"); print_r((float)1.3144345); echo("\n"); print_r((bool)false); echo("\n"); print_r((string)"test"); echo("\n"); print_r((object)new stdClass()); echo("\n"); print_r((unset)null); echo("\n"); print_r((array)array(1, 2, 3)); echo("\n"); ?>
1000 1.3144345 test stdClass Object ( ) Array ( [0] => 1 [1] => 2 [2] => 3 )
Übergibt man als zweiten Parameter ein (bool)true an print_r(), dann gibt die Funktion ihr Ergebnis als String zurück, statt diesen direkt auszugeben:
<?php echo(print_r((int)1000, true)); echo("\n"); echo(print_r((float)1.3144345, true)); echo("\n"); echo(print_r((bool)false, true)); echo("\n"); echo(print_r((string)"test", true)); echo("\n"); echo(print_r((object)new stdClass(), true)); echo("\n"); echo(print_r((unset)null, true)); echo("\n"); echo(print_r((array)array(1, 2, 3), true)); echo("\n"); ?>
1000 1.3144345 test stdClass Object ( ) Array ( [0] => 1 [1] => 2 [2] => 3 )
4. var_export()
Die Ausgaben von var_export() im Beispiel, auch hier fehlen viele Datentypen in der Ausgabe:
<?php var_export((int)1000); echo("\n"); var_export((float)1.3144345); echo("\n"); var_export((bool)false); echo("\n"); var_export((string)"test"); echo("\n"); var_export((object)new stdClass()); echo("\n"); var_export((unset)null); echo("\n"); var_export((array)array(1, 2, 3)); echo("\n"); ?>
1000 1.3144345 false 'test' stdClass::__set_state(array( )) NULL array ( 0 => 1, 1 => 2, 2 => 3, )
Wie bei print_r() kann auch an var_export() ein (bool)true als zweiter Parameter übergeben werden, sodass die Funktion ihr Ergebnis per return zurückgibt:
<?php echo(var_export((int)1000, true)); echo("\n"); echo(var_export((float)1.3144345, true)); echo("\n"); echo(var_export((bool)false, true)); echo("\n"); echo(var_export((string)"test", true)); echo("\n"); echo(var_export((object)new stdClass(), true)); echo("\n"); echo(var_export((unset)null, true)); echo("\n"); echo(var_export((array)array(1, 2, 3), true)); echo("\n"); ?>
1000 1.3144345 false 'test' stdClass::__set_state(array( )) NULL array ( 0 => 1, 1 => 2, 2 => 3, )
5. Eigene Funktion
Natürlich lässt sich auch eine eigene Funktion schreiben, um Variablen auszugeben. Diese kann entsprechend vom Design her angepasst werden, während eine Anpassung der Standardfunktionen (var_dump, print_r, var_export) nicht möglich ist. Die nachfolgende Funktion showVar() erwartet eine Variable als Parameter und wandelt diese in die Form „(datentyp)inhalt” um (Rückgabe als String). Bei Arrays wird gleiches auch auf alle Schlüssel und Werte angewendet. Bei Objekten wiederum wird „(object)Klassenname” zurückgegeben.
<?php function showVar($var, $showType=true) { if (is_int($var)) { // Integers return ($showType ? '(int)'.$var : $var); } else if (is_float($var)) { // Floats return ($showType ? '(float)'.round($var, 4) : round($var, 4)); } else if (is_string($var)) { // Strings return ($showType ? '(string)"'.$var.'"' : '"'.$var.'"'); } else if (is_bool($var)) { // Booleans $var = ($var ? 'true' : 'false'); return ($showType ? '(bool)'.$var : $var); } else if (is_array($var)) { // Arrays $out = ($showType ? '(array)(' : '('); $c = ''; foreach ($var as $key=>$val) { if ($c!=='') { $c .= ', '; } // Schluessel => Wert $c .= showVar($key, $showType) . ' => ' . showVar($val, $showType); } $out .= $c . ')'; return $out; } else if (is_object($var)) { // Objekte return ($showType ? '(object)'.get_class($var) : get_class($var)); } else if (is_resource($var)) { // Resourcen return '(resource)'; } else if (is_null($var)) { // NULL return 'NULL'; } else { // anderes bzw. unbekanntes return '('.gettype($var).')?'; } } $null = null; $int = 1000; $float = 1.7773; $bool = false; $string = "example"; $obj = new stdClass(); $arr1 = array(1, 2, 3); $arr2 = array(array(1, 2), array("hello", "world")); echo('$null: '.showVar($null)."\n"); echo('$int: '.showVar($int)."\n"); echo('$float: '.showVar($float)."\n"); echo('$bool: '.showVar($bool)."\n"); echo('$string: '.showVar($string)."\n"); echo('$obj: '.showVar($obj)."\n"); echo('$arr1: '.showVar($arr1)."\n"); echo('$arr2: '.showVar($arr2)); ?>
$null: NULL $int: (int)1000 $float: (float)1.7773 $bool: (bool)false $string: (string)"example" $obj: (object)stdClass $arr1: (array)((int)0 => (int)1, (int)1 => (int)2, (int)2 => (int)3) $arr2: (array)((int)0 => (array)((int)0 => (int)1, (int)1 => (int)2), (int)1 => (array)((int)0 => (string)"hello", (int)1 => (string)"world"))