IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

7. diel - Štandardy jazyka PHP - PSR-6 (cachovací rozhranie)

Cache (vyslovujeme [keš], v češtine cache) je bežne využívaná k zrýchleniu všetkých aplikácií a projektov. Vďaka tomu sú cachovací systémy jednou z najbežnejších súčasťou všetkých frameworkov. Mnoho knižníc si tak tvoria aj svoje vlastné cachovací systémy s rôznym stupňom funkcionality. Kvôli rozdielom potom vývojári musia mať znalosti o viacerých systémoch súčasne, z ktorých niektoré môžu, ale aj nemusia podporovať zrovna tie funkcie, ktoré potrebujú. Zároveň samotní developeri cachovacích knižníc musí voliť medzi podporou obyčajné časti frameworkov a veľkým množstvom nadbytočných tried umožňujúcich kompatibilitu.

PSR-6: Caching Interface

Tieto problémy by malo vyriešiť práve spoločné rozhranie, ktoré PSR-6 definuje. Vývojári potom môžu očakávať rovnaké výsledky od rôznych systémov a tie naopak musia implementovať len niekoľko rozhraní namiesto celej škály prídavných tried.

Kľúčové koncepty

Najskôr začneme u kľúčových konceptov.

Pool

Pool alebo fond reprezentuje kolekciu prvkov v cachovacím systéme. Všetky cachovatelné prvky sú z poolu vrátené ako objekty a akákoľvek interakcie s týmito objektmi musí prebiehať za pomocou poolu.

Items

Item (prvok) reprezentuje objekt alebo hodnotu v poole, ktorému zodpovedá kľúč. Tento kľúč je primárnym a unikátnym identifikátorom a MUSÍ byť nezmeniteľný. Hodnota ale MÔŽE byť zmenená.

Definícia

V štandarde sú použité pojmy, ktoré si najskôr vysvetlíme.

Calling Library / Volajúci knižnica

Calling Library je knižnica alebo časť kódu, ktorá využíva cache, ale o vnútorné implementácii cachovacích systémov nemá žiadne informácie.

Implementing Library / národné implementačné knižnica

Implementing Library implementuje štandard na účely dodania cachovacích systémov pre volajúcich knižnice. MUSÍ dodať rozhranie Cache\CacheItemPoolInterface a Cache\CacheItemInterface a MUSÍ podporovať aspoň TTL funkcionalitu. Čo jednotlivé rozhrania definujú si vysvetlíme na konci článku v samostatnej kapitole.

TTL (The Time To Live) / Doba životnosti

TTL je čas, po ktorý je objekt braný ako platný. Ide o dobu od vzniku objektu až po jeho zánik.

Expirácie

Expirácie je naozajstný čas, kedy vyprší doba životnosti objektu. Väčšinou sa počíta pridaním TTL k času, kedy prvok vznikol, ale môže byť zmenený. Národné implementačné knižnice MÔŽU dobu životnosti objektu skrátiť, ale MUSÍ sa k prvku správať ako k neplatnému, ak príslušný čas už vypršal. Národné implementačné knižnice MÔŽU použiť predvolené nastavenie TTL, ak ale žiadne neexistuje, MUSÍ prvok uložiť do cache navždy (kým je to možné).

Kľúč

Kľúč je reťazec o minimálne jednom znaku, ktorý je unikátny pre daný prvok vo vyrovnávacej pamäti. Národné implementačné knižnice MUSÍ podporovať kľúče v UTF-8 kódovanie až do dĺžky 64 znakov, ktoré obsahujú veľké a malé písmená, celé čísla, podčiarkovník a bodku v akomkoľvek poradí. Podporu ďalších znakov alebo dlhších reťazcov MÔŽU pridať. NEMÔŽU však pridať podporu znakov {}, (), /, \, @ a :, pretože tie sú vyhradené pre budúce potreby a rozšírenia. Zároveň sú národné implementačné knižnice zodpovedné za svoje vlastné escape sekvencie. MUSÍ byť ale schopné vrátiť pôvodné kľúč bez modifikácií.

Hit a miss

Ak sa volajúci knižnica pokúsi vyhľadať prvok podľa kľúča a je nájdený, má platnú dobu životnosti a dáta nie sú žiadnym spôsobom poškodená, jedná sa o tzv. Cache hit. V opačnom prípade sa jedná o tzv. Cache miss, dokonca aj keď je len prekročená doba životnosti. Volajúci knižnice by MALI overiť isHit() v každom volaní get().

Odloženie (deferred)

Odložené uloženie do vyrovnávacej pamäte poukazuje na skutočnosť, že prvok nemusí byť ihneď permanentne uložený poolom (napríklad do databázy). Pool MÔŽE pozdržať uloženie prvku, aby mohli byť využité hromadné operácie podporované niektorými pamäťovými modulmi. Pool MUSÍ zabezpečiť, že akýkoľvek pozdržané prvok je nakoniec uložený a dáta nie sú stratené. MÔŽE je tiež uložiť predtým, ako o to požiada volajúci knižnica. Keď volajúci knižnica použije metódu commit(), všetky zostávajúce odložené prvky MUSÍ byť uložené. Národné implementačné knižnica MÔŽE použiť akúkoľvek logiku, aby určila, kedy odložené prvky uložiť (napríklad destruktor, vytvorenie všetkých naraz pri zavolaní save(), maximálneho počtu prvkov). Žiadosť o prvok vo vyrovnávacej pamäti, ktorá bola odložená, MUSÍ vrátiť odložený, ale ešte neuložený, prvok.

Dáta

Všetky knižnice MUSÍ podporovať všetky serializovatelný dátové typy (tie, ktoré je možné ukladať a prenášať priamo):

  • String - reťazca znakov o náhodné dĺžke v akomkoľvek formátovania, ktoré PHP podporuje
  • Integer - všetky celé čísla až do 64-bit signed (= záporné aj kladné čísla)
  • Float - čísla s desatinnou čiarkou až do veľkosti 64-bit signed (= záporné aj kladné čísla)
  • Boolean - pravda / nepravda (true / false)
  • Null - prázdna hodnota
  • Array - indexované polia, vrátane multidimenzio­nálnych polí o ľubovoľnej dimenzii
  • Object - akýkoľvek objekt, ktorý podporuje bezstratovú (de) serializáciu, napr. $o == unserialize(serialize($o). Objekty MÔŽU využívať dva tzv. Magických metód __sleep() a __wakeup() alebo podobných funkcionalít jazyka, ak je potreba .

Ak nie je možné presne vrátiť uloženú hodnotu z akéhokoľvek dôvodu, tak MUSÍ knižnice odpovedať pomocou cache miss namiesto poškodenými dátami.

Zachytávanie chýb

Hoci cachovanie nemalým dielom prispieva k výkonnosti aplikácie, nemalo by nikdy byť nepostrádateľnou súčasťou. Preto by chyba v cachovacím systéme NEMALA vyústiť v zlyhaní aplikácie. Z tohto dôvodu NESMIE národné implementačné knižnice hádzať iné výnimky, než aké sú definované v rozhraní. Tiež BY MALI zachytiť akékoľvek chyby alebo výnimky a neumožniť im "vybuble".

Národné implementačné knižnice BY MALI tieto chyby logovať alebo je inak odovzdať na spracovanie administrátorom.

Ak volajúci knižnica požiada o zmazanie jedného alebo viacerých prvkov, alebo o zmazanie celého poolu, NESMIE vyústiť v chybu, ak hľadaný prvok neexistuje. Koncová podmienka je rovnaká (pool je prázdny a prvok je zmazaný - kľúč neexistuje), a preto nie je dôvod na vyvolanie chyby.

Rozhranie

V priebehu bola spomenutá rôzne rozhrania. Čo vlastne pre štandard znamenajú?

CacheItemInterface

Definuje prvok v cachovacím systéme. Každý prvok MUSÍ byť spojený so špecifickým kľúčom, ktorý môže byť priradený na základe implementujícího systému a je zvyčajne odovzdávaný pomocou Cache\CacheItemPoolInterface objektu.

Objekt Cache\CacheItemInterface zapuzdruje ukladanie a vyvolávanie nacachovaných prvkov a je generovaný pomocou objektu Cache\CacheItemPoolInterface, ktorý je zároveň zodpovedný za prvotné nastavenie a priradenie kľúčov. MUSÍ byť schopný uložiť a vrátiť akýkoľvek serializovatelný dátový typ (viď sekcia dáta na začiatku článku).

Volajúci knižnice NESMIE vytvárať inštancie prvkov. Môžu je len volať z poolu pomocou metódy getItem(). Zároveň by NEMALI predpokladať, že prvok vytvorený pomocou jednej národné implementačné knižnice je kompatibilný s poolom iné.

Rozhranie CacheItemInterface môže vyzerať napríklad takto:

<?php
namespace Psr\Cache;

interface CacheItemInterface
{
    public function getKey();
     /**
     * Vrací klíč pro cachovaný prvek
     *
     * Klíč je poskytnut implementující knihovnou, ale měl by být
     * k dispozici ostatním volajícím, pokud je zapotřebí
     *
     * @return string
     *   Klíč
     */

    public function get();
     /**
     * Získá hodnotu prvku z cache spojené s daným klíčem
     *
     * Vrácená hodnota musí být identická s hodnotou uloženou pomocí
     * set()
     * Pokud isHit() vrátí false, tato metoda MUSÍ vracet null
     * Null však může být uložená hodnota, proto musí rozlišovat
     * mezi „nic nenalezeno“ a „nalezeno null“
     *
     * @return mixed
     */

    public function isHit();
    /**
     * Potvrdí, jestli hledání skončilo jako cache hit
     * NESMÍ nastat souběh mezi voláním isHit() a get()
     *
     * @return bool
     *   Pokud se jedná o cache hit, vrací true, jinak false
     */

    public function set($value);
    /**
     * Uloží hodnotu reprezentovanou cachovaným prvkem
     *
     * @param mixed $value
     *   Serializovatelná hodnota, kterou chceme uložit
     *
     * @return static
     */

    public function expiresAt($expiration);
    /**
     * Nastaví expiraci pro daný prvek NA určitou dobu
     *
     * @param \DateTimeInterface|null $expiration
     *   Doba, kdy MUSÍ být prvek považován za expirovaný
     *   Pokud nastavíme null, MŮŽE být použita výchozí hodnota
     *   nebo prvek uložíme po maximální možnou dobu
     *
     * @return static
     *   Volaný objekt
     */
    public function expiresAfter($time);
    /**
     * Nastaví expiraci, ale PO určité době
     *
     * @param int|\DateInterval|null $time
     *   Předáváme integer, který reprezentuje čas ve vteřinách
     *   nebo null jako v předchozí funkci
     *
     * @return static
     */
}

CacheItemPoolIn­terface

Hlavným účelom tohto rozhrania je prijímať kľúče od volajúci knižnice a vracať objekty s nimi spojené. Zároveň funguje ako vstupný bod pre interakciu s celou cache kolekcií. Akákoľvek inicializácia a konfigurácia poolu je prenechaná národné implementačné knižnici.

Ako príklad rozhranie CacheItemPoolInterface si môžeme uviesť potrebné toto:

<?php

namespace Psr\Cache;

/**
 * CacheItemPoolInterface vytváří CacheItemInterface objekty
 */
interface CacheItemPoolInterface
{
    public function getItem($key);
    /**
     * Vrací prvek reprezentující daný klíč
     *
     * MUSÍ vracet CacheItemInterface objekt, a to i v případě
     * cache miss. NESMÍ vracet null
     *
     * @param string $key
     *   Klíč hledaného objektu
     *
     * @throws InvalidArgumentException
     *    V případě neplatného klíče MUSÍ být vyhozena
     * \Psr\Cache\InvalidArgumentException
     *
     * @return CacheItemInterface
     */

    public function getItems(array $keys = array());
    /**
     * Vrací sadu traversable (možné iterovat pomocí foreach) prvků
     * @param string[] $keys
     *   Pole klíčů
     *
     * @throws InvalidArgumentException
     *   Pokud i jeden klíč je neplatný, MUSÍ být hozena
     *   \Psr\Cache\InvalidArgumentException
     *
     * @return array|\Traversable
     *   Traversable kolekce cachovaných prvků i s jejich klíči
     *   Cachovaný prvek bude vrácen pro každý klíč, i když nebyl
     *   nalezen
     *   Pokud nespecifikujeme žádný klíč, MUSÍ být vrácena prázdná
     *   traversable kolekce
     */

    public function hasItem($key);
    /**
     * Potvrdí, jestli cache obsahuje hledaný prvek
     *
     * Tato metoda může kvůli výkonu pozdržet získání hodnoty.
     * To by mohlo vyústit v souběh s metodou get().
     * Abychom se této situaci vyhnuli, je doporučeno používat
     * spíš isHit().
     *
     * @param string $key
     *
     * @return bool
     *   True, pokud prvek existuje, jinak false
     */

    public function clear();
    /**
     * Odstraní všechny prvky v poolu
     *
     * @return bool
     *   True, jestliže byla operace úspěšná
     */

    public function deleteItem($key);
    /**
     * Odstraní prvek z poolu
     *
     * @param string $key
     *   Klíč prvku
     *
     * @throws InvalidArgumentException
     *   Pokud klíč není platný, MUSÍ být vyhozena
     *   \Psr\Cache\InvalidArgumentException
     *
     * @return bool
     *  True, pokud byl prvek úspěšně odstraněn
     */

    public function deleteItems(array $keys);
    /**
     * Odstraní více prvků z poolu
     *
     * @param string[] $keys
     *   Pole klíčů prvků, které mají být odstraněny
     *
     * @throws InvalidArgumentException
     *   Pokud jakýkoliv klíč není platný
     *
     * @return bool
     */

    public function save(CacheItemInterface $item);
    /**
     * Okamžitě uloží cachovaný prvek (př. do databáze)
     *
     * @param CacheItemInterface $item
     *   Prvek, který chceme uložit
     *
     * @return bool
     *   True, pokud byla operace úspěšná, jinak false
     */

    public function saveDeferred(CacheItemInterface $item);
    /**
     * Určí, že má být prvek uložen později
     *
     * @param CacheItemInterface $item
     *   Prvek, který má být uložen
     *
     * @return bool
     * False, pokud prvek nemohl být zařazen do fronty, nebo pokud pokus o uložení selhal. Jinak true.
     */

    public function commit();
    /**
     * Uloží pozdržené prvky
     *
     * @return bool
     *   True, pokud byly všechny prvky úspěšně uloženy,
     *   nebo nebyly žádné, které by na uložení čekaly.
     */
}

CacheException

Je určené pre zachytávanie kritických chýb ako napríklad pri pripojení ku cache servera alebo overovania. Akákoľvek výnimka hodená národné implementačné knižnicou MUSÍ mať toto rozhranie.

InvalidArgumen­tException

Rozhranie pre neplatné cache argumenty implementuje rozhranie CacheException:

<?php
namespace Psr\Cache;

/**
 * Rozhraní pro neplatné cache argumenty
 *
 * Kdykoliv je metodám předán neplatný argument, musí být hozena
 * výjimka, kterou implementuje
 * Psr\Cache\InvalidArgumentException.
 */
interface InvalidArgumentException extends CacheException
{
}

V ďalšej lekcii, Štandardy jazyka PHP - PSR-7 (Všeobecná špecifikácie a prúdy) , sa zameriame na štandard PSR-7, ktorý sa zaoberá rozhraním pre HTTP komunikáciu.


 

Predchádzajúci článok
Štandardy jazyka PHP - PSR-4 a autoloader
Všetky články v sekcii
Štandardy jazyka PHP
Preskočiť článok
(neodporúčame)
Štandardy jazyka PHP - PSR-7 (Všeobecná špecifikácie a prúdy)
Článok pre vás napísala Miroslava Škutová
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
.
Aktivity