Debugger: odstranění tryError, catchError a toStringException
- David Grudl
- Nette Core | 8218
Nette interně používalo dvojici metod Debugger::tryError & catchError pro zachycení E_NOTICE nebo E_WARNING a jejich následné zpracování a také metodu Debugger::toStringException řešící problém, že v PHP se nesmí vyhodit výjimka v metodě __toString().
Pokud jste tyto metody používali, vězte, že jsou označeny jako deprecated a budou v dalších verzích odstraněny.
Důvod je především ten, že vytvářely závislost na třídě Debugger. Z hlediska čistoty a přenositelnosti kódu je taková závislost kontraproduktivní. Podstatné však je, že dnes lze stejného výsledku dosáhnout i bez těchto metod.
tryError & catchError
Klasický use case vypadal takto:
Nette\Diagnostics\Debugger::tryError(); // zachytávání chyb
$ini = parse_ini_file($file, TRUE); // funkce, která může generovat E_WARNING
if (Nette\Diagnostics\Debugger::catchError($e)) { // pokud došlo k chybě, bude převedena na výjimku
throw new InvalidArgumentException('parse_ini_file(): ' . $e->getMessage(), 0, $e);
}
bez Debuggeru se dá věc zapsat takto:
set_error_handler(function($severity, $message) { // zachytávání chyb
restore_error_handler();
throw new InvalidArgumentException("parse_ini_file(): $message"); // konverze na výjimku
});
$ini = parse_ini_file($file, TRUE); // funkce, která může generovat E_WARNING
restore_error_handler(); // ukončení zachytávání chyb
Výsledný kód takřka stejně dlouhý, jen vyhození výjimky se trošku nelogicky nachází nad volanou funkcí. Závislost na Debuggeru je ale pryč.
Pokud je chyba signalizovaná návratovou hodnotou, lze použít ještě jednodušší řešení:
$ini = @parse_ini_file($file, TRUE); // funkce, která může generovat E_WARNING
if ($ini === FALSE) {
$error = error_get_last();
throw new InvalidArgumentException("parse_ini_file(): $error[message]"); // konverze na výjimku
}
toStringException
Use case vypadal takto:
public function __toString()
{
try {
return $this->toString();
} catch (\Exception $e) { // výjimka se nesmí vyhodit
Diagnostics\Debugger::toStringException($e); // necháme ji zobrazit Debuggerem
}
}
bez Debuggeru se dá zapsat takto:
public function __toString()
{
try {
return $this->toString();
} catch (\Exception $e) {// výjimka se nesmí vyhodit
trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()}", E_USER_ERROR);
}
}
Výsledný kód je opět stejně dlouhý, nicméně bez závislosti na Debuggeru a tedy přenositelný. Co je podstatné, tak že na funkčnosti to nijak neubralo, protože Debugger dokáže situaci detekovat, dostane se k výjimce a zobrazí ji stejně jako dosud. Kdybych vymyslel dřív, jak tohoto dosáhnout, toStringException() by vůbec nevznikla ;-)
- Filip Procházka
- Moderator | 4668
Vyzkoušel jsem
Je to super no :) Jen nevím kolik % lidí odchytává výjimky do
$e
. Určitě víc jak půlka, ale těžko říct.