Maak je CakePHP app sneller: Caching
Veel mensen vinden het lastig om de verschillende caching opties in CakePHP te begrijpen, laat staan te gebruiken. In dit artikel ga ik in op de details, zodat je alles te weten komt over caching in Cake.
Over Caching
Caching is bedoeld om de server load te verlagen. Zo kun je bijvoorbeeld een pagina met een langzame query cachen, zodat hij niet elke request uitgevoerd hoeft te worden. Caching is niet bedoeld als permanente opslag, en zou ook nooit om die reden gebruikt mogen worden. Vuistregel: cache alleen dingen die je opnieuw kunt genereren.
In Cake zijn er verschillende niveau's waarop je kunt cachen:
- Pagina- of elementniveau
Op dit niveau cache je het resultaat van een hele pagina, bijvoorbeeld een detailview. - Per-request Query caching
Dit niveau van caching gebeurd in de Cake Core. Per request wordt het resultaat van een query bewaard, zodat de query niet nogmaals uitgevoerd hoeft te worden wanneer je dezelfde data nogmaals opvraagt. - Cache-'iets'
Vage benoeming, ik weet het, maar op dit niveau kun je alles cachen. Van een array tot een string.
Algemeen
In Cake zijn er verschillende cache engines. In dit artikel ga ik uit van de FileEngine. Hiermee kun je al snel resultaten behalen, terwijl APC, XCache of Memcache meer configuratie vereisen.
Voordat caching werkt, moet debug op 0 staan, Cache.disable false en Cache.check true zijn.
Pagina- of elementniveau
Als je aan de gang wilt met caching op pagina of element niveau, moet je allereerst de CacheHelper activeren. Dit doe je door hem toe te voegen aan bijvoorbeeld je AppController:
var $helpers = array('Cache');
Daarnaast moet je aangeven welke acties je gecached wilt hebben, en voor hoelang. Dit kan in de variabele $cacheAction, of in de functie zelf. De laatste vind ik zelf het meest prettig werken. $cacheAction mag vanalles zijn, als strtotime() er maar wat mee kan.
function read($slug = null)
{
$this->cacheAction = "1 week";
}
Als je nu je browser opstart, en de pagina opvraagt, dan zul je zien dat er in app/tmp/cache/views/ een bestandje tevoorschijn is gekomen: de cache versie van jouw view.
Sommige dingen niet cachen.
Soms is het nodig om bepaalde delen van de pagina niet te cachen, zoals de blokje waarin de gebruikersnaam van de op dat moment ingelogde gebruiker, of de $session->flash()'es bijvoorbeeld. Als je deze namelijk zou cachen, zou niemand ze meer zien, als de eerste die de pagina opvroeg er geen had.
<cake:nocache>
<?php $session->flash(); ?>
</cake:nocache>
Dit kun je oplossen door gebruik te maken van de <cake:nocache> tags. Alles tussen de tags wordt niet gecached, en wordt uitgevoerd op het moment dat de gecachte versie wordt opgevraagd. Let wel op dat data uit de controller niet beschikbaar is!
Per-request Query caching
In de Modellaag van je applicatie kun je ook resultaten van een query cachen, per request. Wat je hiermee kunt? Op deze manier voorkom je dat dezelfde query meerdere keren in dezelfde request wordt uitgevoerd. Je kunt query caching aanzetten door de variabele $cacheQueries true te maken.
Deze manier van cachen gebeurd alleen in het geheugen, en is geldig zolang de request bezig is.
Cache-'iets'
Als laatste is er de algemene vorm van caching. Door gebruik te maken van Cache::read() en Cache::write() kun je werkelijk alles opslaan in je cache. Verschillende toepassingen waar je aan kunt denken: Twitterberichten via de API binnenhalen en vervolgens cachen (ruwe data (array), of de kant en klare html (string)), of het resultaat van een query cachen, zoals ik doe op deze site. Voorbeeldtoepassing:
function search()
{
if(!empty($this->params['url']['search']))
{
App::import('Sanitize');
$input = Sanitize::escape($this->params['url']['search']);
if(Cache::read('query.'.Inflector::slug($input).'.articles', 'search') === false)
{
[..]
$articles = $this->Article->find('all' [..]);
Cache::write('query.'.Inflector::slug($input).'.articles', $articles, 'search');
}
else
{
$articles = Cache::read('query.'.Inflector::slug($input).'.articles', 'search');
}
}
}
Waarom ik niet gebruik maak van de pagina caching methode? Omdat ik niet gebruik maak van de Cake parameters, maar van de standaard GET parameters, ziet Cake search?q=foo en search?q=cake als dezelfde pagina. Door gebruik te maken van Cache::write() en Cache::read() kan ik de resultaten afzonderlijk opslaan en weer opvragen.
Conclusie
Afsluitend wil ik het volgende meegeven: test, test, test! Controleer alles driedubbel om te zien of er nergens 'verkeerde' data terecht komt, dat zou lullig zijn. Anyway; door slim gebruik te maken van je resources, kun je je applicatie een pak sneller maken, ook als je website niet zo heel veel bezoekers heeft!
Reacties
Er zijn op dit moment geen reacties.
Permalink
geen reacties