Artikel » View based caching - ein HOWTO
View based caching - ein HOWTO
Während einer Diskussion im
developers-guide.net Forum wurde die Idee des
view based caching geboren. Ausgelöst durch einen Einwurf von
Alberto begannen wir
über Performance-Optimierungen und verschiedene Caching-Methoden zu sprechen. Am Ende der
Diskussion kamen die Beteiligten darüber ein, dass das Caching von einzelnen Teilen einer
Applikation ein effektives Mittel für die Steigerung der Performance ist.
Dies kann durch eine auf cURL basierende Lösung, die von
Alberto vorgestellt wurde oder
durch view based caching erreicht werden. Der Vorteil von view based caching ist, dass die Applikation
selbst nicht an die Cache-Strategie angepasst werden muss. Dieser Artikel beschreibt die technische
Idee und die Umsetzung mit den Mitteln des Adventure PHP Framework.
Um die Idee besser verdeutlichen zu können, zunächst ein paar Worte zum Thema
Views.
In APF-Terminologie sind Views nichts anderes als Templates, die von anderen eingebunden werden. Ein
Webseiten-Layout, das importdesign-Tags beinhaltet definiert bereits Views. Wie im Kapitel
Klassen
beschrieben wird, erzeugt die PageController-Implementierung einen Objektbaum aus den bekannten Tags
in einem Template.
Jeder Tag besteht dabei aus seiner Definition - etwa
APF-Template
<my:tag attr1="value1" attr2="value2" />
- und der Implementierung der Funktion des Tags, sog. TagLibs. Jede TagLib muss das folgende Interface
implementieren:
PHP-Code
class my_taglib_tag extends Document
{
function my_taglib_tag(){
}
function onParseTime(){
}
function onAfterAppend(){
}
function transform(){
}
}
Details zur Implementierung von TagLibs und welche Funktionalität sich hinter den einzelnen
Methoden versteckt bzw. verstecken müssen, kann im Tutorial
TagLibs erstellen
nachgelesen werden.
Wie kann diese Information nun genutzt werden um view based caching zu implementieren? Ganz einfach:
dank der generischen PageController-Implementierung kann der Entwickler eigene Taglibs erzeugen, die
die bisherige Funktion einer Taglib erweitern. Das bedeutet, dass der bisherige Template-Include-Mechanismus
einfach um eine Caching-Funktion ergänzt werden muss - die Basis von view based
caching!
Wie im Kapitel
Standard TagLibs
beschrieben ist, kann der
<core:importdesign />-Tag dazu verwendet werden,
ein Template als Kind des aktuellen DOM-Knoten einzubinden. Hierzu muss lediglich der Namespace des
Templates und dessen Namen in den Attributen des Tags spezifiziert werden. Wie bereits weiter oben
bemerkt, kann dieser Tag dazu verwendet werden, um einen View innerhalb eines Layout-Templates zu
definieren. Ein View kann dabei z.B. den Header, Footer oder die Navigation einer Seite beinhalten.
Da wir nur den Inhalt von speziellen Views einer Seite cachebar gestalten wollen, kann diese TagLib
als Basis genutzt werden.
Um das zu verdeutlichen, ist in der folgenden Codebox die Implementierung der Taglib dargestellt:
PHP-Code
class core_taglib_importdesign extends Document
{
function core_taglib_importdesign(){
parent::Document();
}
function onParseTime(){
$Namespace = trim($this->__Attributes['namespace']);
$Template = trim($this->__Attributes['template']);
if(isset($this->__Attributes['context'])){
$this->__Context = trim($this->__Attributes['context']);
}
if(isset($this->__Attributes['incparam'])){
$IncParam = $this->__Attributes['incparam'];
}
else{
$IncParam = 'pagepart';
}
...
$this->__loadContentFromFile($Namespace,$Template);
$this->__extractDocumentController();
$this->__extractTagLibTags();
}
}
Die eigentliche Funktion des Tags besteht darin, die Attribute des Tags zu analysieren, den Inhalt
des gewünschten Templates zu laden und den Inhalt zu analysieren. Hierzu werden die Methoden
__extractDocumentController() und
__extractTagLibTags() genutzt,
die bereits im der Klasse
Document definiert sind. Es fehlt also nur noch der Caching-Part!
Das Framework beinhaltet mit dem CacheManager eine flexible Caching-Komponente mit verschiedenen
Backends. In diesem Fall ist jedoch ein einfacher Text-Cache-Mechanismus ausreichend, der im Kapitel
Text-Cache-Provider
der CacheManager-Dokumentation beschrieben ist. Um diesen verwenden zu können, ist es notwendig,
eine Konfiguration anzulegen. Diese hat gemäß der Dokumentation die folgende Gestalt:
APF-Konfiguration
[view_based_cache]
Cache.Provider.Namespace = "tools::cache::provider"
Cache.Provider.Class = "TextCacheProvider"
Cache.Active = "true"
Cache.BaseFolder = "/path/to/my/cache/base/folder"
Cache.Namespace = "view::one"
Zum Schreiben und Lesen des Caches kann der folgende Code verwendet werden:
PHP-Code
// get the cache manager
$cM = &$this->__getServiceObject('tools::cache','CacheManager');
$cM = &$cMF->getCacheManager('view_based_cache');
// calculate cache key
$cacheKey = /* ... */;
// read the cache
$cacheContent = $cM->getFromCache($cacheKey);
// write to the cache
if($cacheContent === null){
$cacheContent = /* generate content */;
$cM->writeToCache($cacheKey,$cacheContent);
}
Um den Inhalt eines Views cachen zu können, werden nun die beiden Teile aus Kapitel 3.1 und
3.2 zusammengefügt:
PHP-Code
class cache_taglib_importdesign extends core_taglib_importdesign
{
var $__CacheContent = null;
function cache_taglib_importdesign(){
// call the parent's constructor to fill the known taglib list
parent::core_taglib_importdesign();
}
function onParseTime(){
// get the cache manager
$cMF = &$this->__getServiceObject('tools::cache','CacheManagerFabric');
$cM = &$cMF->getCacheManager('view_based_cache');
// calculate the cache key
$cacheKey = md5(
$this->getAttribute('namespace').
$this->getAttribute('template').
get_class($this->__ParentObject)
);
// try to read from the cache
$this->__CacheContent = $cM->getFromCache($cacheKey);
// check if the document was cached before. If not
// execute the parent's onParseTime()
if($this->__CacheContent === null){
parent::onParseTime();
}
}
function transform(){
// generate the node's output or return the cached content
if($this->__CacheContent === null){
// get the cache manager
$cM = &$this->__getServiceObject('tools::cache','CacheManager');
$cM = &$cMF->getCacheManager('view_based_cache');
// calculate the cache key
$cacheKey = md5(
$this->getAttribute('namespace').
$this->getAttribute('template').
get_class($this->__ParentObject)
);
// generate output and cache it
$output = parent::transform();
$cM->writeToCache($cacheKey,$output);
// return the tag's output
return $output;
}
else{
return $this->__CacheContent;
}
}
}
Wie im Code-Block zu sehen ist, wurden die Methoden
onParseTime() und
transform()
um das Cache-Handling ergänzt. Um innerhalb der Klasse erkennen zu können, ob der Inhalt
aus dem Cache gelesen werden kann, wurde die private Variable
__CacheContent eingeführt.
Bitte beachten Sie, dass der Code teilweise redundant vorhanden ist. Diese wurde jedoch nur zu
Demonstrationszwecken so gewählt.
Die Anwendung der Caching-TagLib unterscheidet sich kaum von der Verwendung des
<core:importdesign /> Tags. Der einzige Unterschied ist, dass eine Konfigurationssektion
für den CacheManager existieren muss:
APF-Template
<core:addtaglib namespace="" prefix="cache" class="importdesign" />
<cache:importdesign namespace="my::namespace" template="my_template" />
Dank der PageController-Implementierung des APF ist es sehr einfach, view based caching auf Basis
von TagLibs zu implementieren. Um eine wiederverwendbare und in allen Bereichen einsetzbare TagLib
zu erhalten, sollte die in Kapitel 3.3 abgedruckte Klasse noch um ein oder zwei weitere Attribute
erweitert werden, die die Cache-Konfiguration und den Cache-Schlüssel übergeben. Das stellt
sicher, dass die TagLib innerhalb der Applikation einfacher an unterschiedlichen Stellen gleichzeitig
genutzt werden kann.
Beim Thema Cache-Verwaltung hat der Entwickler zwei Möglichkeiten: manuelles Leeren des Caches
oder der Einsatz eines Caching-Backends, das Cache-Lebenszeit unterstützt. Falls die Notwendigkeit
besteht, sich selbst erneuernden Cache zu haben, so kann der CacheManager wie im Kapitel
Erweiterung
aufgezeigt erweitert werden.
Um das oben gezeigte Konzept lokal ausprobieren zu können, habe ich eine Beispiel-Implementierung
für PHP 5 erstellt, die die in Kapitel 5 besprochenen Optimierungen bereits enthalten. Um das
Beispiel lokal auszuführen, bitte die Datei
view-based-caching-...-php5.zip
herunterladen und im DOCUMENT_ROOT des Webservers entpacken. Bitte beachten Sie dabei, dass der
Benutzer, unter dem der Webserver ausgeführt wird, Schreibrechte auf das aktuelle Verzeichnis
besitzt. Falls ein anderer Ordner als Cache-Basis-Ordner verwendet werden soll, einfach die Datei
/apps/config/tools/cache/sites/vbc/DEFAULT_cacheconfig.ini anpassen.
Kommentare
Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese
hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.
Für diesen Artikel liegen aktuell keine Kommentare vor.