Valná většina uživatelů systému WordPress ani neví, že nějaká taková funkce existuje. Není divu, ona se totiž až do verze PHP 8 chovala velice nenápadně, ale využívána je opravdu často. Upravuje totiž dobu, po kterou se může vykonávat PHP skript.

V nastavení PHP existuje možnost zakázat volání nějaké funkce z bezpečnostních, nebo i jiných důvodů s pomocí direktivy disable_functions. Po tomto nastavení často šahají sdílené webhostingy, protože například v případě funkce set_time_limit by mohlo dojít k většímu vytěžování zdrojů serveru na úkor ostatních webů na daném webhostingu.

Pokud jsme v případě PHP 7 a starších verzí zavolali zakázanou funkci, dostali jsme warning s následující hláškou.

Warning: set_time_limit() has been disabled for security reasons in ... on line ...

Protože se jedná pouze o warning, bylo možné tuto hlášku potlačit pomocí zavináče (@) a pokračovat dál, jako by se nic nestalo. Lze proto ve starších verzích WordPressu, Joomly a různých pluginů narazit na následující volání.

@set_time_limit(0);

Tento (značně lenivý) přístup pak změnil příchod PHP 8, kdy byl tento vcelku neškodný warning povýšen na error a začaly se dít věci. Tato funkce je totiž často užívána v případech, kdy dochází k nějakému AJAXovému volání. Uživatel často ani nepozná problém. Jedinou indicií je většinou pouze načítací obrazovka, která nikdy nezmizí.

Fatal error: Uncaught Error: Call to undefined function set_time_limit() in ...:...

Pro populární systémy přišlo řešení vcelku rychle. Můžeme se totiž dotázat, jestli funkce existuje a až poté ji v případě splnění podmínky zavolat. Jednoduché že? Problém je v tom, že ačkoliv jádra těchto systémů aktualizaci s následujícím kódem obdržela, valná většina pluginů a komunitního kódu již ne.

if (!function_exists('set_time_limit')) {
    set_time_limit(0);
}

Najednou se tedy dostáváme do stavu, kdy část systémů funguje s pomocí výše popsaného opraveného kódu a část padá, protože obsahuje již zastaralý workaround. Jako řešení se tedy nabízí polyfill této metody a to nám i nová verze PHP 8 dovoluje! V minulých verzích to možné nebylo, protože na zakázanou funkci nebylo nahlíženo stejně jako na neexistující. Sama dokumentace PHP zmiňuje tuto změnu následovně: „Disabled functions are now treated exactly like non-existent functions. Calling a disabled function will report it as unknown, and redefining a disabled function is now possible.“.

// Jednoduchý polyfill pro PHP 8
if (!function_exists('set_time_limit')) {
    function set_time_limit($sec) {
        return false; // Vracíme informaci o tom, že volání selhalo.
    }
}

A fungovat nám to najednou bude krásně! Ale jen pro PHP 8. Pokud tento kód zkusíme spustit ve starších verzích PHP, selže. Příčinou je právě výskyt zakázané funkce v seznamu definovaných funkcí a výsledkem je tak chyba s informací, že nemůžeme funkci deklarovat vícekrát.

Fatal error: Cannot redeclare set_time_limit() in ... on line ...

Protože nám function_exists pro vypnutou funkci napříč verzemi PHP vrátí false, musíme nějak toto volání omezit na PHP verze 8. S pomocí PHP_VERSION a version_compare() je to vcelku triviální. Výsledný kód, který bude problém řešit napříč verzemi by mohl vypadat následovně:

if (!function_exists('set_time_limit') && version_compare(PHP_VERSION, '8.0.0', '>=')) {
    function set_time_limit($sec) {
        return false; // Vracíme informaci o tom, že volání selhalo.
    }
}

V případě WordPressu pak můžeme tuto funkci vložit např. do souboru wp-config.php a tím vyřešit problém s voláním zakázené funkce, který by nám mohl shazovat nejčastěji cron a AJAX volání.

Potřebujete pomoc?

Neváhejte a napište nám! Web s vámi nainstalujeme, nastavíme a zabezpečíme. Vy se nemusíte o nic starat. Stačí vyplnit náš kontaktní formulář nebo se nám ozvat na [email protected].