bigWeb/Debug/Dumper to narzędzie funkcjonalnie odpowiadające funkcji var_dump Jego przewagą jest sposób prezentacji danych, a także dodatkowe informacje ułatwiające debugowanie aplikacji.
Najpoważniejszą wadą Dumpera jest to, że jest on dość obciążający dla aplikacji gdyż uzyskanie informacji o pliku i linii, w której dump został wywołany wymaga każdorazowo rzucenia wyjątku. Dlatego też w wersji produkcyjnej Dumper powinien być wyłączony
UWAGA! Biblioteka zaprezentowana w przykładach wymaga min PHP 5.3 z uwagi na użycie przestrzeni nazw. Ponieważ jednak nie na wszystkich serwerach jest już PHP w wersji obsługującej przestrzenie nazw przygotowałem także wersję Dumpera nie wymagającą ich użycia. w takim przypadku wywołanie bigWeb\Debug\Dumper::factory(); należy zastąpić poprzez wywołanie bigWeb_Debug_Dumper::factory(); i analogicznie w przypadku innych klas. Wersja Dumpera dla PHP < 5.3 zawarta jest w archiwum zip bigWeb\Debug\Dumper do ściągnięcia.
Instalacja
include_once('./Debug.php');
Można też użyć autoloadera. Wszystkie klasy potrzebne do działania Dumpera zdefiniowane są w pliku „Debug.php”. Wyjątkiem jest FirePHP, który należy dodać osobno jeśli chcemy wyświetlać dane w konsoli javascript
include_once('./FirePHP.php');
Podstawowe użycie
dump('some data');
w wyniku otrzymamy:
Dumpa można wywołać z wieloma parametrami o różnych wartościach równocześnie.
$str = 'text'; $int = 7; $arr = array('foo', 'bar'); $ob = new ArrayObject(); $bool = FALSE; dump($str, $int, $arr, $ob, $bool);
Ukrywanie komunikatów
Aby zapobiec wyświetlaniu jakichkolwiek komunikatów przez dumpera należy go wyłączyć.
bigWeb\Debug\Dumper::setEnabled(FALSE); dump('it should not show');
Aby ponownie włączyć:
bigWeb\Debug\Dumper::setEnabled(TRUE);
Definiowanie alternatywnych logerów
Domyślnie dumper do zrzutu danych używa wbudowanej funkcji var_dump jednak klasa Dumpera jest zbudowana w oparciu o wzorzec projektowy Obserwator, gdzie obserwatorami są wyspecjalizowane klasy do logowania i prezentacji zrzucanych danych. Dzięki temu możemy wybierać sposób logowania informacji.
Możemy zapisywać dane w pliku – przydatne np. przy testowaniu przekierowań
$d = bigWeb\Debug\Dumper::factory(); $o = new bigWeb\Debug\Dumper\FileDump();
Koniecznym jest wskazanie katalogu w którym będą zapisywane logi. Katalog ten musi mieć oczywiście ustawione prawa do zapisu
$o->setDir(dirname(__FILE__)); $d->attach($o); $d->notify('foo');
wynik zostanie zapisany w pliku /home/www/bigWeb/Debug/2012-01-12.log.php
TIME: 20:46:18 FILE: /home/zh/www/Debug/example.php LINE: 71 ET: 0.001143 MU: 1.55 mb MPU: 1.67 mb ----------| 'foo' |---------- foo .----------------------------
Można też skorzystać z dobrodziejstw FireBuga – dodatku do Firefoxa i wyświetlać dane w konsoli javascript. W tym przypadku musimy najpierw załadować bibliotekę FirePHP będącej „pomostem” pomiędzy PHP i FireBugiem.
include_once('./FirePHP.php'); $d = bigWeb\Debug\Dumper::factory(); $d->attach(new bigWeb\Debug\Dumper\FireDump()); $d->notify('bar');
wynik pokarze nam się w konsoli FireBug-a
UWAGA! Ponieważ informacje do FireBuga są przesyłane za pomocą nagłówków HTTP biblioteka FirePHP wymaga buforowania wyjścia (output bufering). Koniecznym jest zatem użycie funkcji ob_start() w przeciwnym razie można się spotkać z błędem „headers already sent error”
Łańcuch wywołań
Niekiedy chcemy wiedzieć jakie funkcje i metody zostały wywołane nim został wykonany kod w danym miejscu. Aby zobaczyć cały łańcuch wywołań należy ustawić flagę show_trace na TRUE.
function foo() { $d = bigWeb\Debug\Dumper::factory(); $d->attach(new bigWeb\Debug\Dumper\VarDump()); $d->setShowTrace(TRUE); $d->notify('Show chain requests'); } function bar() { foo(); } bar();
Array
(
[0] => Array
(
[file] => /home/www/bigWeb/Debug/example.php
[line] => 97
[function] => notify
[class] => bigWeb\Debug\Dumper
[type] => ->
[args] => Array
(
[0] => Show chain requests
)
)
[1] => Array
(
[file] => /home/www/bigWeb/Debug/example.php
[line] => 101
[function] => foo
[args] => Array
(
)
)
[2] => Array
(
[file] => /home/www/bigWeb/Debug/example.php
[line] => 104
[function] => bar
[args] => Array
(
)
)
)
Praca na serwerze produkcyjnym
W zasadzie Dumper powinien być wyłączony na serwerze produkcyjnym bo obciąża aplikację, a ponadto może wyświetlać dane wrażliwe. Nie mniej w pewnych wyjątkowych okolicznościach możemy chcieć go użyć. Musimy wcześniej przewidzieć taką sytuację i dodatkowo skonfigurować przynajmniej jedną z instancji Dumpera ustawiając tak zwany secret_key
$d = bigWeb\Debug\Dumper::factory(); $d->attach(new bigWeb\Debug\Dumper\FireDump()); $d->setSecretKey('verysicretkey');
Aby te dane były widoczne należy wywołać url metodą GET z parametrem secret_key=1. W tym przypadku będzie to
example.php?verysicretkey=1
bigWeb\Debug\Dumper::setEnabled(FALSE); $d->notify('Visible when set secret_key');
aby ponownie włączyć:
bigWeb\Debug\Dumper::setEnabled(TRUE);
Jeśli wywołamy url metodą GET z sekretnym kluczem, Dumper ustawia ciasteczko debugcookie o wartości wywiedzionej z secret_key. Od tej pory nie trzeba już dodawać do adresu żadnego specjalnego parametru. Jeśli jednak chcielibyśmy wyłączyć debugowanie należy wywołać url z secret_key=0
example.php?verysicretkey=0
Tworzenie funkcji pomocniczych
Tworzenie obiektu i dodawanie obserwatorów nie jest zbyt wygodnym rozwiązaniem. Narzędzie do debugowania powinno być extremalnie proste i szybkie w użyciu. Dlatego warto sobie zdefiniować funkcję pomocniczą – podobną do „debug();”
function dump_all() { $_args = func_get_args(); static $d = null; if ( $d === null ) { // Proszę zwrócić uwagę na wywołanie metody factory z parametrem $level = 3 $d = bigWeb\Debug\Dumper::factory(3); $o = new bigWeb\Debug\Dumper\FileDump(); $o->setDir(dirname(__FILE__)); $d->attach($o); $d->attach(new bigWeb\Debug\Dumper\FireDump()); $d->attach(new bigWeb\Debug\Dumper\VarDump()); } call_user_func_array(array($d, 'notify'), $_args); } dump_all('foo bar');
wynik zostanie zapisany w pliku
TIME: 20:46:44 FILE: /home/zh/Praca/bigWeb/Debug/example.php LINE: 155 ET: 0.006137 MU: 1.59 mb MPU: 1.67 mb ----------| 'foo bar' |---------- foo bar .--------------------------------
w konsoli FireBug-a
oraz wyświetlony w przeglądarce:
UWAGA! Od wartości level zależy prawidłowe wskazanie linii oraz pliku, w którym wywołano dumpa. Domyślnie level = 1. Jeżeli metoda „notify” jest zagnieżdżona w funkcji pomocniczej to wartość level powinna być inkrementowana (level = 2). Jeśli dodatkowo metoda „notify” jest wywoływana za pośrednictwem funkcji „call_user_func_array” to należy ustawić level = 3
$d = bigWeb\Debug\Dumper::factory(1); function d1($param) { $d = bigWeb\Debug\Dumper::factory(2); // ... $d->notify($param); } function d2($param) { $_args = func_get_args(); $d = bigWeb\Debug\Dumper::factory(3); // ... call_user_func_array(array($d, 'notify'), $_args); }
UWAGA! Jeśli masz już zdefiniowaną funkcję „dump” w swojej aplikacji to po dołączeniu kodu Dumpera otrzymasz wszystkomówiący wyjątek. Poinformuje Cię on, że musisz zdefiniować sobie funkcję pomocniczą o innej nazwie. Należy zakomentować kod wywołujący wyjątek lub też dołączyć kod Dumpera w sposób umożliwiający przechwycenie wyjątka i utworzyć funkcję pomocniczą np. o nazwie „d”.
try { include_once("Debug.php"); } catch (bigWeb\Debug\Exception $e) { function d() { $_args = func_get_args(); static $d = null; if ( $d === null ) { $d = bigWeb\Debug\Dumper::factory(3); $d->attach(new bigWeb\Debug\Dumper\VarDump()); } call_user_func_array(array($d, "notify"), $_args); } }
Napisana przeze mnie klasa nie zastąpi zaawansowanych i rozbudowanych narzędzi debugowania i profilowania aplikacji jednak jest prosta w użyciu nie związana stricte z żadnym frameworkiem, przez co łatwo ją zaadaptować zarówno do pracy z Zend Frameworkiem, Symfony, Kohaną czy jakimkolwiek innym – napisanym w PHP – skryptem. Biblioteka zwraca wyniki w postaci pokolorowanego kodu przy okazji pokazując czas wykonania oraz wielkość użytych zasobów. Zapomniany var_dump potrafi zmusić programistę do przeszukiwania plików projektu. W przypadku Dumpera nie ma takiego zagrożenia gdyż każdorazowo wskazuje on ścieżkę do pliku oraz nr linii, w której funkcja robiąca zrzut danych została wywołana.
Serdecznie zapraszam wszystkich do wypróbowania Dumpera oraz wszelkich uwag na temat wdrożeń i ewentualnych błędów.



