PHP-Klasse cache

Einleitung
Voraussetzung
Versionsgeschichte
Installation
Einbindung in deine Webseite
Dokumentation

Einleitung

Manche Aufgaben beim verarbeiten eines Webserver-Requests brauchen Zeit. Sei es ein rekursiver Verzeichnisscan, ein aufwändiges Query oder Requests auf andere Server.
Solche zeitaufwändigen Aufgaben möchte man nicht bei jedem Seitenaufruf ausführen, weil es den Seitenaufbau immer arg verlangsamt, sondern nur "gelegentlich". Dazu speichert man einmalig das Ergebnis in einem Cache und verwendet den Cache solange man es für sinnvoll erachtet.

Diese Klasse verwende ich auf dieser Webseite zum Cachen von HTML-Code, RSS-Daten und Grafiken.
Weiterhin ist diese Klasse in Version 1 auch seit einigen Jahren auf der Webseite vom Schweizer Radio DRS (SRF Radio; www.drs.ch) im Einsatz.


Seitenanfang


Voraussetzung

  • PHP 5

Seitenanfang


Versionsgeschichte

  • 2012-05-17 - Version 2.1
    • geänderte Methode: isExpired() liefert Wert als bool (vorher Wert in Sekunden);
    • neue Methode: iExpired() liefert Wert in Sekunden
    • 2012-01-31 - Version 2.0
      • neu: es können alle serialisierbaren Variablen gecacht werden - also auch Arrays und Objekte - nicht nur Strings, wie in Version 1
      • Methode write() erweitert: als 2. Parameter kann eine Verfallszeit mitgegeben werden, die mit in der Cachedatei gespeichert wird
      • neue Methode: isExpired() zum einfacheren Feststellen, ob Cache veraltet ist (bedingt Verwendung des neuen 2. Parameters für write())
      • neue Methode: isNewerThanFile([Referenzdatei]) - zum einfacheren Feststellen, ob Cache veraltet ist
      • neue Methode: cleanup() - Löschen alter Cachedateien
    • 2011-08-27 - Version 1.1 - mehr Kommentare im PHP Code; sCacheFile is private
    • 2009-07-20 - Version 1.0 - erste öffentliche Version

    Seitenanfang


    Installation

    Download

    Download:
    cache_class_php.zip (13 kB)

    Auspacken

    Kopieren Sie die Datei cache.class.php in ihr PHP-Verzeichnis. Sie kann auch in einem beliebigen Unterordner abgelegt werden.


    Seitenanfang


    Einbindung in deine Webseite

    Basics: Füllen und Lesen des Caches

    (1)
    Mit einer include_once/ require_once ist die Klasse zu laden.

    (2)
    Mit der Initialisierung sind 2 Parameter anzugeben:
    • der Name deiner Applikation / deines Moduls
      Im Hintergrund wird für die Applikation ein Unterverzeichnis angelegt. Dann können verschiedene Module dieselbe ID verwenden. Und man kann einfacher das Cacheverzeichnis eines Moduls leeren.
    • eine ID für die Daten
      Die ID kann ein beliebiger Text oder auch eine Zahl sein. Bei RSS Feeds kann man so direkt die URL des Feeds mitgeben; bei Datenbank-Queries kann es eine Basis ID sein, für die die Daten ermittelt wurden.

    (3)
    Die Funktionen read() und write([Daten , [Expire]]) lesen bzw. schreiben den Cache-Inhalt.

    (4)
    Mit am wichtigsten ist die Frage: wie lange man ich den Cache verwenden und wann muss ich diesen erneuern?
    Es gibt mehrere Varianten:
    1. Zunächst werden die Daten mit write([Daten]) geschrieben.
      Mit der Funktion getAge() kann man das Alter des Caches in Sekunden ermitteln. Ist es false, so gibt es noch keinen Cache.
      Man kann den Cache anlegen/ erneuern lassen, wenn noch kein Cache existiert oder das Alter des Cache eine Toleranzschwelle übersteigt.
      Das ist eine Methode von Version 1; es sollte bevorzugt eine der nachfolgend erwähnten Varianten gewählt werden.
    2. mit der Methode write() gibt man als 2. Paramter eine Verfallszeit (Expire) in Sekunden mit. Diese Verfallszeit wird mit in der Cachedatei abgelegt.
      Dann kann man mit isExpired() feststellen, ob der Cache veraltet ist (negative Werte = Zeit in Sekunden bis Verfall; positive Werte = wie lange der Cache verfallen ist)
    3. Wenn man den Cache basierend auf einer anderen Datei aufbaut, kann man die Zeitstempel von Quelldatei und Cachedatei zum Vergleich heranziehen.
      Die Funktion isNewerThanFile([Dateiname-der-Referenzdatei]) gibt die Differenz der letzten Änderung in Sekunden zurück (negative Werte = Cachdatei ist älter als Referenzdatei).
      Die Referenzdatei ist der komplette Dateiname, den der Webserver finden können muss (lokal oder NFS Share etc.).
      Beispiele wären: ein verkleinertes Vorschaubild wird erst dann erneuert, wenn sich die Quelldatei geändert hat; oder: meine Tabelle mit Batch-Kommandos und Beispielen basieren auf einer CSV Datei - der Cache wird erst neu geschrieben, wenn ich die CSV Datei aktualisiere.
    Ein Coderumpf als Ausgangslage zu 2) für eigene Entwicklungen sieht so aus:

    
    $sContent='';
    $iTtl=60*5; // 5 min als max. zulaessiges Alter
    
    require_once("/php/cache.class.php");
    $myCache=new Cache("mein-modul","Aufgaben-ID");
    
    if($myCache->isExpired()) {
        // Cache existiert nicht oder ist veraltet
        // hier folgt Code, der $sContent neu auffuellt ...
        $sContent=...
    
        // ... und im Cache ablegen
        $myCache->write($sContent, $iTtl);
    
    } else {
        // Cache-Daten lesen
        $sContent=$myCache->read();
    }
    
    // Ausgabe
    echo $sContent;
    
    
    PHP: cache - einfacher Code-Rumpf


    ... und ein Beispiel zu 3) zum Vergleich des Zeitstempels. $sCsvFile enthält nachfolgend den Dateinamen des Quellfiles:

    require_once("/php/cache.class.php");
    $sCsvFile="Name_der_Quelldatei.csv"
    
    $myCache=new Cache("mein-modul","Aufgaben-ID");
    $sContent=$myCache->read(); // einmal den Inhalt lesen
    
    // Vergleich des Alters des Cache mit dem einer Referenzdatei
    if (!$sContent || !$myCache->isNewerThanFile($sCsvFile)) {
    
        // hier folgt Code, der $sContent neu auffuellt ...
        $sContent=...
    
        // ... und im Cache ablegen
        $myCache->write($sContent);
    };
    
    // Ausgabe
    echo $sContent;
    
    
    PHP: cache - Beispiel mit Vergleich des Zeitstempels einer Referenzdatei


    Löschen von Cachefiles

    Man kann von einem zu cachenden Inhalt einen einzelnen Cache gezielt löschen. Dazu muss das entsprechende Objekt initialisiert und die die Methode delete() aufgerufen werden.

    require_once("/php/cache.class.php");
    $myCache=new Cache("mein-modul","Aufgaben-ID");
    $myCache->delete(); // einzelnen Cache loeschen
    
    PHP: cache - Beispiel mit Vergleich des Zeitstempels einer Referenzdatei

    Um im Cacheverzeichnis alle Cache-Dateien löschen, die älter als n Sekunden sind, gibt es die cleanup-Methode. Das Cache-Objekt ist mit einer beliebigen Modul-ID zu initialisieren.

    require_once("/php/cache.class.php");
    $o=new Cache("mein-modul");
    $o->cleanup(60*60*24*1); // alle Cachefiles des Moduls "mein-modul" älter 1 Tag löschen
    
    PHP: Löschen des Caches eines Moduls


    Initialisiert man die Klasse ganz ohne Modul und ruft die cleanup Methode auf, so werden alle cachefiles aller Module aufgeräumt.

    require_once("/php/cache.class.php");
    $o=new Cache();
    $o->cleanup(0); // alle Cachefiles aller Module löschen
    
    PHP: Löschen des Caches aller Module

    Anm.:
    • Der Parameter von cleanup() ist das max. erlaubte Alter der Cachedateien in Sekunden. Ist der Wert 0, so werden *alle* Cachedateien gelöscht.
    • Die cleanup()-Mehode ignoriert alle anderen Dateitypen, die keine Cachedateien sind.
    • Leere Verzeichnisse ab dem Cache-Root werden gelöscht.


    Seitenanfang


    Dokumentation

    Class: Cache
    Methoden verstecken

    public __construct( $sModule = '.', $sCacheID = '.')
    constructor
    @param string $sModule name of module or app that uses the cache
    @param string $sCacheID cache-id (must be uniq for a module; used to generate filename of cachefile)
    @return boolean
    private _cleanupDir( $sDir, $iTS) ... all param(s) required
    recursive cleanup of a given directory; this function is used by
    public function cleanup()
    @param string $sDir full path of a local directory
    @param string $iTS timestamp
    @return true
    private _getAllCacheData()
    private function _getAllCacheData() - read cachedata and its meta infos
    @return array array with data, file stat
    private _getCacheFilename()
    private function _getCacheFilename() - get full filename of cachefile
    @return string full filename of cachefile
    public cleanup( $iSec = false)
    Cleanup cache directory; delete all cachefiles older than n seconds
    Other filetypes in the directory won't be touched.
    Empty directories will be deleted.

    Only the directory of the initialized module/ app will be deleted.
    $o=new Cache("my-app"); $o->cleanup(60*60*24*3);

    To delete all cachefles of all modules you can use
    $o=new Cache(); $o->cleanup(0);

    @param int $iSec max age of cachefile; older cachefiles will be deleted
    @return true
    public delete()
    public function delete - delete a single cachefile if it exist
    @return boolean
    public dump()
    public function dump() - dump variables of cache class
    @return true
    public getAge()
    public function getCacheAge() - get age in seconds of exisiting cachefile
    @return int age in seconds; -1 if cachefiles does not exist
    public getExpire()
    public function getExpire() - get TS of cache expiration
    @return int unix ts of cache expiration
    public getTtl()
    public function getTtl() - get TTL of cache in seconds
    @return int get ttl of cache
    public isExpired()
    public function isExpired() - cache expired? To check it
    you must use ttl while writing data, i.e.
    $oCache->write($sData, $iTtl);
    @return bool cache is expired?
    public iExpired()
    public function iExpired() - get time in seconds when cachefile expires
    you must use ttl while writing data, i.e.
    $oCache->write($sData, $iTtl);
    @return int expired time in seconds; negative if cache is not expired
    public isNewerThanFile( $sRefFile) ... all param(s) required
    function isNewerThanFile($sRefFile) - is the cache (still) newer than
    a reference file? This function returns difference of mtime of both
    files.
    @param string $sRefFile local filename
    @return integer time in sec how much the cache file is newer; negative if reference file is newer
    public read()
    public function getCacheData() - read cachedata if it exist
    @return various cachedata or false if cache does not exist
    public setData( $data) ... all param(s) required
    public function setData($data) - set cachedata into cache object
    data can be any serializable type, like string, array or object
    Remark: You additionally need to call the write() method to store data in the filesystem
    @param various $data data to store in cache
    @return boolean
    public setTtl( $iTtl) ... all param(s) required
    public function setTtl() - set TTL of cache in seconds
    You need to write the cache data to ap
    Remark: You additionally need to call the write() method to store a new ttl value with
    data in the filesystem
    @param type $iTtl ttl value in seconds
    @return int get ttl of cache
    public touch()
    public function touch() - touch cachefile if it exist
    For cachedata with a ttl a new expiration will be set
    @return boolean
    public write( $data = false, $iTtl = -1)
    Write data into a cache.
    - data can be any serializable type, like string, array or object
    - set ttl in s (from now); optional parameter
    @param various $data data to store in cache
    @param int $iTTL time in s if content cache expires (min. 0)
    @return bool success of write action
    Properties verstecken

    public $sModule = false
    a module name string is used as relative cache path
    @var string
    public $sCacheID = false
    id of cachefile (filename will be generated from it)
    @var string
    private $_sCacheDir = false
    where to store all cache data - it can be outside docRoot. If it is
    below docRoot think about forbidding access
    If empty it will be set in the constructor to [webroot]/~cache/
    or $TEMP/~cache/ for CLI
    @var string
    private $_sCacheFile = false
    absolute filename of cache file
    @var string
    private $_sCacheExt = cacheclass2
    fileextension for storing cachefiles (without ".")
    @var string
    private $_tsExpire = -1
    Expiration timestamp;
    It will be calculated with current time + ttl in the write() method
    TTL can be read with getExpire()
    @var integer
    private $_iTtl = -1
    TTL (time to live) in s;
    TTL can be set in methods setTtl($iTtl) or write($data, $iTtl)
    TTL can be read with getTtl()
    @var integer
    private $_aCacheInfos = false
    cachedata and file infos of cachefile (returned array of php function stat)
    @var array

    Seitenanfang