Jak napsat error handler v PHP?
Pokud píšete vlastní error handler pro PHP, je bezpodmínečně nutné dodržet několik pravidel. Jinak může nabourat chování dalších knihoven a aplikací, které nečekají v error handleru zradu.
Parametry
Signatura handleru vypadá takto:
function errorHandler(
int $severity,
string $message,
string $file,
int $line,
array $context = null // pouze v PHP < 8
): ?bool {
...
}
Parametr $severity
obsahuje úroveň chyby
(E_NOTICE
, E_WARNING
, …). Pomocí handleru nelze
zachytávat fatální chyby, jako třeba E_ERROR
, takže těchto
hodnot nikdy nebude parametr nabývat. Naštěstí fatální chyby v podstatě
z PHP zmizely a byly nahrazeny za výjimky.
Parametr $message
je chybová hláška. Pokud je zapnutá
direktiva html_errors,
jsou speciální znaky jako <
apod. zapsány jako HTML entity,
takže do podoby plain textu je musíte dekódovat.
Ovšem pozor, některé znaky jako entity zapsány nejsou, což je bug.
Samotné zobrazování chyb v čistém PHP je tak náchylné na XSS.
Parametry $file
a $line
představují název
souboru a řádek, kde k chybě došlo. Pokud chyba nastala uvnitř
eval()
, bude $file
doplněný o tuto informaci.
A nakonec parametr $context
obsahuje pole lokálních
proměnných, což představuje pro debugování užitečnou informaci, ale od
PHP 8 je zrušený. Pokud má handler fungovat v PHP 8, parametr vynechte nebo
mu dejte výchozí hodnotu.
Návratová hodnota
Návratová hodnota handleru může být null
nebo
false
.
Hodnota false
říká, že se zavolá ještě standardní PHP
handler. Ten podle konfigurace PHP může chybu vypsat, zalogovat atd.
Zpřístupní ji také funkci error_get_last().
Potlačené chyby
V PHP lze potlačit zobrazování chyb buď pomocí shut-up operátoru
@
nebo pomocí error_reporting()
:
// potlač chyby úrovně E_USER_DEPRECATED
error_reporting(~E_USER_DEPRECATED);
// potlač všechny chyby při volání fopen()
$file = @fopen($name, 'r');
I při potlačení chyb dojde k volání handleru. Proto je nejprve nutné ověřit, zda chyba je potlačená, a pokud ano, tak musíme zpracování ukončit:
if (($severity & error_reporting()) !== $severity) {
return false;
}
Zpracování musíme v tomto případě ukončit pomocí
return false
, aby se spustil ještě standardní error handler. Ten
nic nevypíše a nezaloguje (protože je chyba potlačená), ale zajistí, že
chybu půjde zjistit pomocí error_get_last()
.
Ostatní chyby
Pokud handler chybu zpracuje (například vypíše vlastní hlášku atd.),
už není potřeba volat standardní handler. Sice pak nebude možné chybu
zjistit pomocí error_get_last()
, ale to v praxi nevadí, protože
tato funkce se používá především v kombinaci s shut-up operátorem.
Pokud naopak handler chybu nezpracuje, měl by vrátit false
,
aby ji nezatajil.
Zanechat komentář