k47.cz  — každý den dokud se vám to nezačne líbit
výběr foto Praha povídky kultura
TECH ▞▞ kolo | twitter RSS

Nette CachedControl

1. 11. 2008 (před 11 lety) — k47 (CC by-nc-sa) (♪)

Jed­no­du­chá Nette kom­po­nenta s in­te­gro­va­ným ke­šo­vá­ním.


Když jsem zjis­til, že se mi moje na­pra­sené Nette kom­po­nenty, které se sta­rají o zdejší pa­tičky a hla­vičky a další vě­cičky, ne­kešují i když by měli, roz­hodl jsem se přijít se sy­té­mo­věj­ším ře­še­ním. Proto jsem si napsal velice jed­no­du­chou abs­traktní kom­po­nentu, která kešuje a ra­zantně zeštíhlí zdě­děné kom­po­nenty (někdy i na pár řádek). Je to sice ma­lič­kost, ale někomu by se mohla snad hodit.

Tady je celý zdro­jový kód (li­cence je taková ta svo­bodná):

<?php

abstract class CachedControl extends Control{

  const CACHE_NAMESPACE = 'application/output';
  protected $expire = 1200;
  protected $cacheKey;
  protected $templateFile;
  protected $tags = array();

  abstract function renderContent();
  protected function startup() {}
  protected function addSuffix() { return '';}

  function render() {

    if (isset(Environment::getConfig('app')->cachedControl->expire)) {
      $this->expire = Environment::getConfig('app')->cachedControl->expire;
    }

    $cache = Environment::getCache(self::CACHE_NAMESPACE);
    $this->cacheKey = $this->getClass() . $this->getName() . $this->addSuffix();

    if (isset($cache[$this->cacheKey])) {
      echo $cache[$this->cacheKey];

    } else {
      $this->template->setFile(dirname(__FILE__) .  $this->templateFile);
      $this->template->registerFilter('TemplateFilters::curlyBrackets');

      $this->renderContent();

      echo $content = $this->template->__toString();

      if ($this->expire && $this->expire > 0) {
        $cache->save(
          $this->cacheKey,
          $content,
          array(
            'expire' => $this->expire,
            'tags' => $this->tags,
          )
        );
      }
    }
  }
}

?>

Zdě­děná kom­po­nenta je potom, co se kódu týče, sym­pa­ticky skromná. Po­hleďte:

<?php

class MenuControl extends CachedControl {
  //adresa šablony vzhledem k umístění komponenty
  protected $templateFile = '/MenuControl.phtml';

  //pole tagů, slouží k invalidaci keše
  protected $tags = array('entry', 'comment');

  public function renderContent(){

    $this->template->menu = MenuSection::findAllAsTree(); //veškerá logika přijde sem

  }
}

Všechno za­jí­mavé přijde do pře­tí­žené abs­traktní metody ren­der­Con­tent. Tam patří celá logika a k lo­kální ša­b­loně se od­tam­tud při­stu­puje nor­málně přes

$this->templte->proměnná = 'XYZ';

Kom­po­nenta se vy­kreslí me­to­dou render. V nad­řa­zené ša­b­loně se tedy nej­spíš vy­skytne něco jako: {? $con­t­rol→render()}

Ex­pi­race keše se dá na­sta­vit člen­skou pro­měn­nou $expire, nebo glo­bálně v kon­fi­gu­rač­ním sou­boru přes klíč app.ca­ched­Con­t­rol.expire (de­faultně je na­sta­ven na 1200, což zna­mená 20 minut).

Další drob­ností je metoda add­Su­f­fix, která je tu pro případ, že se na strán­kách vy­sky­tuje víc růz­ných kom­po­nent stej­ného typu a je nutné je nějak od sebe od­li­šit. Kdyby tomu tak nebylo, soubor s keší by se u všech kom­po­nent jme­no­val stejně a po­cho­pi­telně by se všude vklá­dal jeden a ten daný. Po­u­ží­vám to třeba při ge­ne­ro­vání výpisů no­vi­nek.

Ná­vra­tová hod­nota metody se vloží na konec klíče iden­ti­fi­ku­jící keš a tak stačí add­Su­f­fix jed­no­duše pře­tí­žit:

protected function addSuffix() {
  return $this->year;
}

a keše výpisů no­vi­nek za jed­not­livé roky jsou od sebe od­dě­leny, mají na konci jména sou­boru různý rok a všechno je v cajku.

A to je vše, snad to někomu k něčemu bude.

píše k47 & hosté, ascii@k47.cz