Kompilační chyby v PHP: proč jsou stále problémem?
Programování v jazyce PHP byla vždycky trošku výzva, ale naštěstí prošlo mnohými změnami k lepšímu. Pamatujete na časy před verzí PHP 7, kdy skoro každá chyba znamenala fatal error, což aplikaci okamžitě ukončilo? V praxi to znamenalo, že jakákoli chyba mohla aplikaci zcela zastavit, aniž by programátor měl možnost ji zachytit a náležitě na ni reagovat. Nástroje jako Tracy využívaly magických triků, aby dokázaly takové chyby vizualizovat a logovat. Naštěstí s příchodem PHP 7 se tohle změnilo. Chyby nyní vyvolávají výjimky, jako jsou Error, TypeError a ParseError, které lze snadno zachytávat a ošetřit.
Avšak i v moderním PHP existuje slabé místo, kdy se chová stejně jako ve své páté verzi. Mluvím o chybách během kompilace. Ty nelze zachytit a okamžitě vedou k ukončení aplikace. Jedná se o chyby úrovně E_COMPILE_ERROR. PHP jich generuje na dvě stovky. Vzniká paradoxní situace, že když v PHP načteme soubor se syntaktickou chybou, což může být třeba chybějící středník, vyhodí zachytitelnou výjimku ParseError. Ovšem v případě, že kód je sice syntakticky v pořádku, leč obsahuje chybu odhalitelnou až při kompilaci (například dvě metody se stejným názvem), vyústí to ve fatální chybu, kterou zachytit nelze.
try {
require 'cesta_k_souboru.php';
} catch (ParseError $e) {
echo "Syntaktická chyba v PHP souboru";
}
Bohužel, kompilační chyby v PHP nemůžeme ověřit interně. Existovala
funkce php_check_syntax()
, která navzdory názvu odhalovala
i kompilační chyby. Byla zavedena v PHP 5.0.0, ale záhy odstraněna ve
verzi 5.0.4 a od té doby nikdy nebyla nahrazena. Pro ověření správnosti
kódu se musíme spolehnout na linter z příkazové řádky:
php -l soubor.php
Z prostředí PHP lze ověřit kód uložený v proměnné
$code
třeba takto:
$code = '... PHP kód pro ověření ...';
$process = proc_open(
PHP_BINARY . ' -l',
[['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']],
$pipes,
null,
null,
['bypass_shell' => true],
);
fwrite($pipes[0], $code);
fclose($pipes[0]);
$error = stream_get_contents($pipes[1]);
if (proc_close($process) !== 0) {
echo 'Chyba v PHP souboru: ' . $error;
}
Nicméně režie spouštění externího PHP procesu kvůli ověření jednoho souboru je docela velká. Ale dobrá zpráva přichází s verzí PHP 8.3, která přinese možnost ověřovat více souborů najednou:
php -l soubor1.php soubor2.php soubor3.php
Komentáře
Robert #1
Anebo místo php -l soubor.php lze použít oblíbený eval 🙂 Zhruba nějak takto:
qc_GetPhpSourceError.php
A funkce na kontrolu je pak:
Někdy v php 5.6 jsem to porovnával s php -l a zdálo se mi to lepší …
David Grudl #2
#1 Robert, všechna úskalí, které tento článek popisuje, platí jak pro require(), tak pro eval()
Napište komentář