Talán nem túlzás azt állítani, hogy a Firebug a legjobb dolgok közé tartozik, ami manapság egy JavaScript fejlesztővel történhetnek. A több mint 10 millió letöltés, valamint a tény, hogy - bár maga is kiegészítő - kiegészítőket fejlesztenek hozzá elég bizonyítékul is szolgálhat ennek alátámasztására. Egy ilyen kiegészítőbe futottam bele még valamikor a múlt héten, ami a FirePHP nevet viseli (a nevével ellentétben bármely más szerver oldali nyelvvel használható, ami képes header-öket kiküldeni). Nincs is másra szükségünk csak egy Firefox-ra (ez remélhetőleg már mindenkinek van :)), egy Firebug-ra (ez is esélyes lehet, hogy akad a közelben) és a FirePHP-ra. Meg egy kis szerveroldali scriptre, ami szintén a FirePHP oldaláról tölthető le.

FirePHP

A kiterjesztés mögött rejlő ötlet rettentően egyszerű (és talán éppen ezért olyan fantasztikus): küldjünk ki pár speciális fejlécet valamiféle JSON tartalommal, amit kliens oldalon a kiegészítő feldolgoz és a Firebug segítségével szépen meg is jelenít. Ezek lehetnek több prioritásba sorolható egyszerű szöveges üzenetek (hasonlóak a Firebug beépített üzeneteihez), táblázatok, szépen formázott backtrace-ek vagy akár print_r()-hez hasonló információk változókról.

Nézzünk is egy példát a felhasználásra: jelenítsük meg az oldal legenerálása során küldött SQL lekérdezéseket, külön kiemelve azokat, amik lassabban futnak, mint szeretnénk (a példához Doctrine van használva):

class My_Doctrine_Logger extends Doctrine_EventListener {
    private $queryTime;
    public function preQuery(Doctrine_Event $event) {
        $this->queryTime = microtime(true);
    }
    public function preStmtExecute(Doctrine_Event $event) {
        $this->queryTime = microtime(true);
    }
    public function postQuery(Doctrine_Event $event) {
        $this->logQuery($event->getQuery());
    }
    public function postStmtExecute(Doctrine_Event $event) {
        $this->logQuery($event->getQuery());
    }
    private function logQuery($queryString) {
        $t = microtime(true) - $this->queryTime;
        
        $msg = '['.str_pad(round($t, 5), 7, '0').']: '.$queryString;
        
        if ($t > 0.01) {
            FB::warn('Slow SQL Query: '.$msg);
        }
        else {
            FB::info('SQL Query: '.$msg);
        }
    }
}

És ehhez még nem árt valami ilyesmit is hozzácsapni, hogy a Doctrine tudjon a mi kis osztályunkról:

$conn = Doctrine_Manager::connection( $dsn );
$conn->addListener(new My_Doctrine_Logger());

Az egészből az FB:: kezdetű sorok érdekesek csak. A működésükhöz szükség lehet az output buffering bekapcsolására vagy kellő önuralomra, hogy az utolsó FB::-s hívásig nem nyomunk ki semmit a kimenetre. :)
Ami még érdekes lehet, hogy Ajax-os kérések és Location fejléccel átirányított oldalak hasonló üzenetei is megjelennek a Firebug ablakában, szépen csoportosítva, ezzel végtelenül egyszerűvé téve az Ajaxos kérések és a rájuk érkező válaszok hibamentesítését, sok-sok órát megspórolva ezzel szegény fejlesztőknek. Mindezt természetesen anélkül, hogy az eredeti tartalmat teleszemetelnénk mindenféle nem odavaló dologgal (csúnyán is nézne ki a JSON válasz közepén egy méretes var_dump() kimenet, arról nem is beszélve, hogy a kliens oldalon se tudna vele túl sokat kezdeni a JavaScript).