CakePHP - Vlastní Exception Handler pro lepší přehled nad průšvihy
Článek je psán na verzi CakePHP 2.4.1 a snad mu porozumí začátečník i pokročilý. Pokud najdete chybku, nebo je něco nejasné, křičte na mě v komentářích!
Žádný program není bez chyb (teda alespoň ty moje...), ale je fajn se o nich dozvědět a občas s nimi něco udělat. Cake používá výjimky hlavně pro nenalezené stránky a špatné parametry, ale člověk je může vyvolávat kde chce a jak chce. Jen pozor na výkon, přece jen vytvoření objektu výjimky nějaké prostředky zabere, tak ať to stojí za to!
K věci: Vlastní Exception Handler pro více informací
V původním Exception Handleru toho Cake moc říct nechce. V podstatě jen loguje chybu se špetkou kontextu. Já chci ale vědět, o které URL se mluví a hlavně jak se tam uživatel dostal, takže jdeme vařit podle vlastní kuchařky!
V app/Lib si vytvoříme soubor AppExceptionHandler.php
do kterého umístímě následující:
<?php App::uses('ExceptionHandler', 'Error'); class AppExceptionHandler { public static function handle(Exception $exception) { CakeLog::write(LOG_ERR, self::_getMessage($exception)); ErrorHandler::handleException($exception); } protected static function _getMessage($exception) { // chtělo by to vracet nějaké info return print_r($exception, true); } }
Jednoduchá metoda handle
vlastně jen přijme výjimku, pomocí CakeLog::write
ji zaloguje a pak dá vědět návštěvníkovi, že něco rozbil. Nám je ale v tento moment návštěvník u samého konce trávícího traktu, chceme vytřískat co nejvíce informací z výjimky a proto doplníme metodu _getMessage
o něco užitečnějšího.
protected static function _getMessage($exception) { $message = sprintf("[%s] %s", get_class($exception), $exception->getMessage() ); if (method_exists($exception, 'getAttributes')) { $attributes = $exception->getAttributes(); if ($attributes) { $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true); } } if (php_sapi_name() !== 'cli') { $request = Router::getRequest(); if ($request) { // přidám do zprávy kýžené URL $message .= "\nRequest URL: " . $request->here(); $message .= "\nReferer URL: " . $request->referer(); } } // a přihodím seznam volaných funkcí, které mě k chybě dovedly $message .= "\nStack Trace:\n" . $exception->getTraceAsString(); $message .= "\n---------------------------------------------"; return $message; }
Abych byl upřímný, polovina kódu je pro mě černou magií zkopírovanou z původního exception handleru, ale důležité je, že si ukládám navíc Request URL a Referer URL, plus pro přehlednost přihodím hromadu pomlček, abych se v tom balastu lépe vyznal.
Integrace do aplikace je už maličkost
No, a nakonec je potřeba aplikaci o Exception handleru někde říct, takže v core.php změníme záznam s Configure::write('Exception',...)
na toto:
Configure::write('Exception', array( 'handler' => 'AppExceptionHandler::handle', 'renderer' => 'ExceptionRenderer', 'log' => false ));
...a v bootstrap.php si někde na začátku handler načteme pomocí App::uses('AppExceptionHandler', 'Lib');
. A je to!
Samozřejmě je možné si zobrazit i jiné věci z request objektu, ale nic užitečného mě nenapadá. Článek je inspirován oficiálním návodem a trochou zoufalství při odhalování bugů. Pokud máte nějaké dotazy nebo připomínky, rád si počtu v diskusi pod článkem!