Chybové stránky - Jet\ErrorPages

Smyslem Jet ErrorPages je zapouzdřit a sjednotit logiku pro obsluhu chybových stránek.

Nejprve co je to chybová stránka. To je například "čtyřistačtyřka". Tedy pokud se uživatel dostane například na již neexistující URL, tak potřebujete jednak vrátit správně HTTP kód 404, ale také uživateli zobrazit nějakou informační stránku. Nebo je provoz vašeho webu dočasně pozastaven kvůli údržbě a potřebujete uživatelům kód 503 a opět nějakou info stránku. O ty stránky se musí něco postarat. Něco je musí nějak zobrazit. K tomu se vrátíme později.

Pak je tu aplikace. Ta zjistí (třeba díky Jet MVC), že URL požadavku již není platná. Nebo že báze je aktuálně deaktivována. Nebo že přístup do dané části webu není povolen. A tak dále. Prostě aplikace vyhodnotí tento stav a chce jej obsloužit.

Ovšem to místo v aplikaci které daný stav vyhodnotilo nemá ani ponětí o tom jak má taková "čtyřistačtyřka" vypadat. A vlastně takovému kontroleru nějakého aplikačního modulu (například) do toho vůbec nic není, vůbec mu nepřísluší aby něco takového řešil. Navíc by řešení téhož bylo na nespočtu míst - což je nepřípustné. Proto například onen kontroler potřebuje pouze říct: mám tu "čtyřistačtyřku" - postarejte se o to. Víc už ten kontroler (nebo jakékoliv jiné místo v aplikaci) nezajímá.

A právě k tomu slouží Jet ErrorPages. Pojďme si rovnou ukázat, jak si například kontroler řekne o "čtyřistačtyřku":

ErrorPages::handleNotFound();

A to je celé ... Víc neřeší.

Nebo co když je daná část vašeho projektu dočasně nedostupná?

ErrorPages::handleServiceUnavailable();

Ale není nutné se omezovat. Obsloužit je možné libovolný HTTP kód:

ErrorPages::handleHttp_Headers::CODE_402_PAYMENT_REQUIRED );

To jsme si ukázali příklady použití. Samozřejmě že dále si ukážeme jak definovat ten druhý konec - tedy jak zabezpečit obsluhu. Ale zároveň jsem chtěl ukázat co je cílem a smyslem ErrorPages. Tedy poskytnout transparentní a unifikované rozhraní pro obsluhu všemožných (chybový) stavů.

Inicializace chybových stránek

A nyní si ukážeme jak obsluhu stránek zabezpečit. Jet nabízí hned několik možností, které je možné kombinovat a ty si postupně ukážeme.

View chybových stránek v určitém adresáři

Jedná se o výchozí metodu jak ErrorPages sestaví a zobrazí chybovou stránku. Funguje tak, že v adresáři, který je určen nastavení SysConf_Jet_ErrorPages::getErrorPagesDir() zkusí najít soubor, jehož název odpovídá HTTP kódu a má příponu .phtml. Jedná se vlastně o zjednodušený view skript a je tedy možné v nich skriptovat - nemusí se jednat o striktně statickou stránku.

Než si ukážeme nějaký příklad, tak se provádí zastavme u nastavení cesty adresáře, které se provádí metodou SysConf_Jet_ErrorPages::setErrorPagesDir('somer/dir'). Pokud adresář není nastaven, tak tento způsob zobrazování chybových stránek nefunguje. Pokud jej chcete použít, tak je nezbytné jej nastavit. A při té příležitosti udělejme ještě odbočku k Jet MVC. Pokud jste s Jet MVC již seznámeni, tak víte co je to inicializátor báze. A právě v inicializátorech báze je vhodné místo k nastavení adresáře chybových stránek. Ukažme si příklad z ukázkové aplikace:

namespace JetApplication;

use 
Jet\MVC_Router;
use 
Jet\SysConf_Jet_ErrorPages;
//... ... ..

class Application_Web
{
    
//... ... ...

    /**
     * @param MVC_Router $router
     */
    
public static function initMVC_Router $router ): void
    
{
        
//... ... ...
        
SysConf_Jet_ErrorPages::setErrorPagesDir
            
$router->getBase()->getPagesDataPath$router->getLocale() ) 
        );
    }

}

Jak vidíte, tak ukázková aplikace nastavuje adresář chybových stránek na kořenový adresář stránek aktuální lokalizace aktuální báze. To v praxi znamená, že například v adresáři ~/application/bases/web/pages/cs_CZ/ najdete soubory 401.phtml, 404.phtml a 500.phtml - a to už jsou view pro chybové stránky. Díky tomu může mít každá mutace každé báze své vlastní chybové stránky.

Používání tohoto způsobu je samozřejmě pouze doporučený (i když vřele doporučený) postup. Technicky vás vůbec nic neomezuje a můžete si adresář nasměrovat kam potřebujete, nebo použít jiný způsob.

Zobrazovač - displayer

Může se stát, že vám nebude vyhovovat zobrazování stránek pomocí view a budete si chtít implementovat vlastní logiku zobrazení. S tím, že vše zůstane zachováno (rozhraní pro aplikaci a posílání HTTP hlaviček), pouze se o vygenerování HTML chybové stránky postará vaše logika. Pokud taková situace nastane, tak si můžete pro jednotlivé HTTP kódy definovat tzv. zobrazovače. Ukažme si to rovnou prakticky:

ErrorPages::setDisplayer(404, function() {
    echo 
'This is my 404';
});

Vlastní obsluha - handler

A co když chcete pro určitý kód udělat něco úplně speciálního? Třeba i ponechat systém zobrazení, ale před zobrazením chybové stránky například něco zaznamenat do logu? I to je možné. Stačí si udělat vlastní handler:

ErrorPages::setHandler(404, function() {
    
IO_File::append('my/404.log''404 log record');
});

Jak probíhá obsluha chybových stránek

Ještě si ukažme podrobně co se vlastně děje, když cokoliv z aplikace zavolá například ErrorPages::handleNotFound(); Proces je následující:

  • Zjistí se, zda pro daný HTTP kód (zde 404) existuje handler. Pokud ano, je zavolán a následné proces pokračuje.
  • Pomocí Http_Headers::response( $code ); jsou odeslány HTTP hlavičky.
  • Zjistí se, zda je pro daný HTTP kód definován zobrazovač. Pokud ano, pak zavolán a je mu plně přenecháno zobrazení chybové stránky.
  • Pokud zobrazovač není definován, pak je ověřeno zda je nastaven adresář, který má obsahovat chybové stránky.
  • Pokud adresář je nastaven, pak je v něm hledán soubor, jehož název odpovídá HTTP kódu a přípona je .phtml.
  • Pokud takový soubor / skript existuje, tak je proveden a tím dojde k zobrazení chybové stránky.
  • Běh aplikace je ukončen (pokud nepovinný parametr $application_end nemá hodnotu false).

Přehled metod třídy Jet\ErrorPages

Metoda Význam
public static handle(
int $code,
bool $application_end = true
): void
Obslouží libovolný HTTP kód / stav.

Parametr application_end určuje zda má okamžité po obsluze dojít k ukončení aplikace.
public static handleServiceUnavailable(
bool $application_end = true
): void
Obslouží HTTP kód / stav 503.

Parametr application_end určuje zda má okamžité po obsluze dojít k ukončení aplikace.
public static handleInternalServerError(
bool $application_end = true
): void
Obslouží HTTP kód / stav 500.

Parametr application_end určuje zda má okamžité po obsluze dojít k ukončení aplikace.
public static handleUnauthorized(
bool $application_end = true
): void
Obslouží HTTP kód / stav 401.

Parametr application_end určuje zda má okamžité po obsluze dojít k ukončení aplikace.
public static handleNotFound(
bool $application_end = true
): void
Obslouží HTTP kód / stav 404.

Parametr application_end určuje zda má okamžité po obsluze dojít k ukončení aplikace.
public static display(
int $code
): bool
Pouze zobrazí chybovou stránku pro daný kód (nepošle HTTP hlavičky, nevolá handler, neukončí aplikaci).
public static getErrorPageFilePath(
int $code
): bool|string
Vrátí plnou cestu k view skriptu chybové stránky pro daný kód. Ale pouze za předpokladu, že je nastavena cesta adresáře a daný skript existuje. V opačném případě vrací false.
public static setHandler(
int $code,
callable $callback
): void
Nastaví handler pro daný kód / stav.
public static unsetHandler(
int $code
): void
Zruší handler pro daný kód / stav.
public static setDisplayer(
int $code,
callable $callback
): void
Nastaví zobrazovač pro daný kód / stav.
public static unsetDisplayer(
int $code ): void
Zruší zobrazovač pro daný kód / stav.
Předchozí kapitola
Jet\Db_Backend_PDO_Config
Další kapitola
Session - Jet\Session