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.