Na navigaci | Klávesové zkratky

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. Pokud handler vrátí null, nestane se nic. Pokud vrátí false, zavolá se ještě standardní PHP handler. Ten podle konfigurace PHP může chybu vypsat, zalogovat atd. Co je důležité, tak že také naplní interní informaci o poslední chybě, kterou zpřístupňuje funkce 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 vlastní handler ukončit:

if (!($severity & error_reporting())) {
	return false;
}

Ale pozor, musíme je v tomto případě ukončit pomocí return false, aby se spustil ještě standardní error handler. Ten nic nevypíše ani nezaloguje (protože chyba je potlačená), ale zajistí, že chybu půjde zjistit pomocí error_get_last().

Ostatní chyby

Pokud náš 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 handler naopak chybu z jakéhokoliv důvodu nezpracuje, měl by vrátit false, aby ji nezatajil.

Ukázkový příklad

Takto by vypadal kód vlastního error handleru, který transformuje chyby na výjimky ErrorException:

set_error_handler(function (int $severity, string $message, string $file, int $line) {
	if (!(error_reporting() & $severity)) {
		return false;
	}

	throw new \ErrorException($message, 0, $severity, $file, $line);
});

Mohlo by vás zajímat

Napište komentář

Text komentáře
Kontakt

(kvůli gravataru)



*kurzíva* **tučné** "odkaz":http://example.com /--php phpkod(); \--

phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.