[PHP5] LambdaCache : Système de mise en cache
Posté : 27 mai 2007, 14:04
Je me permets de poster le code d'une classe de mise en cache que j'ai récemment codée dans le cadre d'un ensemble de classes plus complet que je compte mettre en place dans les semaines à venir pour faciliter mes travaux.
La classe propose une compression des fichiers de cache via la fonction gzcompress.
Edit : La gestion du temps de validité du cache serveur est ajoutée. Une classe pour gérer le cache client (via headers HTTP) est ajoutée aussi.
Exemple d'utilisation :
Code source des deux classes :
La classe propose une compression des fichiers de cache via la fonction gzcompress.
Edit : La gestion du temps de validité du cache serveur est ajoutée. Une classe pour gérer le cache client (via headers HTTP) est ajoutée aussi.
Exemple d'utilisation :
<?php
//On initialise le cache client
$cacheHTTP = new LambdaHTTPCache();
//On va afficher une page qui varie selon l'utilisateur, on initialise donc le cache serveur propre à l'utilisateur
$cache = new LambdaCache('cache_'.$_SESSION['username'].'.php');
//On indique au cache client que la page envoyée sera personnelle (pour les proxies)
$cacheHTTP -> setProxy(TRUE, FALSE);
//On indique au cache client la date de dernière modification du fichier de cache serveur
$cacheHTTP -> checkTime($cache -> lastModified());
//On envoie les headers HTTP
$cacheHTTP -> sendHeaders();
//On recalcule la page si la méthode show() ne renvoit rien (sinon elle aura affiché le contenu du cache serveur)
if (!$cache -> show())
{
echo 'Blablabla...';
$cache -> close(); //On écrit le fichier cache et on affiche le résultat
}
?>
Code source des deux classes :
<?php
/*
Lambda System - by Klomac ([email protected])
LambdaCache : This class allows the user to call a cache file or to create it if it doesn't exist yet.
LambdaHTTPCache : This class send the appropriate HTTP headers to use the client cache.
-----------------------------GNU GPL--------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
---------------------------------------------------------------------------
*/
class LambdaCache
{
private $cacheFile; //The cache filename
private $cachePath; //The cache full path
private $compressData; //Define if the gz compression must be used or not
private $cacheContents; //The content of the cache file
private $cacheExists = FALSE; //Indicate if the cache file exists or not
private $timeLimit;
//The errors which may be displayed
private $errors = array(
'Unable to write the cache file',
'Unable to create the cache directory');
public static $cacheDir; //The directory which contains the cache files (must be set by the user)
public $gzLevel = 1; //The level of the gz compression (better is 1, worst is 9)
//Magical methods
public function __construct ($filename, $timeLimit = FALSE, $cacheDir = 'cache/', $compression = TRUE)
{
//We set up the main variables
$this -> cacheFile = $filename;
$this -> cacheDir = $cacheDir;
$this -> cachePath = $cacheDir.$filename;
$this -> timeLimit = is_int($timeLimit) ? $timeLimit : time();
//We check if the directories-tree exists, and create it if it doesn't
$string = '';
$cacheDir = explode('/', $cacheDir);
foreach ($cacheDir AS $dir)
{
if (is_dir($string.$dir) OR @mkdir($string.$dir)) $string .= $dir.'/';
else die ($this -> errors[1]);
}
//We set up the compression level
if ($compression === TRUE) $this -> compressData = TRUE;
elseif (is_int($compression) AND $compression >= 1 AND $compression <= 9)
{
$this -> compressData = TRUE;
$this -> gzLevel = $compression;
}
else $this -> compressData = FALSE;
//We check if the cache file exists, and start a buffer if it doesn't
if (is_readable($this -> cachePath) AND filemtime($this -> cachePath) > (time() - $this -> timeLimit))
{
$this -> cacheExists = TRUE;
if ($this -> compressData)
{
$this -> cacheContents = gzuncompress(file_get_contents($this -> cachePath));
}
else
{
$this -> cacheContents = file_get_contents($this -> cachePath);
}
}
else
{
ob_start();
}
}
//Static methods
public static function clear ($filename, $dir = NULL) //This static method will try to destroy the cache file if it exists
{
$dir = $dir ? $dir : self::$cacheDir;
if (file_exists($dir.$filename)) unlink($dir.$filename);
}
//Public methods
public function lastModified () //This method returns the last-modified timestamp of the cache file
{
if ($this -> cacheExists) return filemtime($this -> cachePath);
else return time();
}
public function show ($print = TRUE) //This method prints (or returns) the cache contents if it exists, or return false
{
if ($this -> cacheExists)
{
if ($print == TRUE)
{
print $this -> cacheContents;
return TRUE;
}
else return $this -> cacheContents;
}
else
{
return FALSE;
}
}
public function close () //This method write the cache file and print the contents
{
$contents = ob_get_clean();
if ($this -> compressData)
{
$cacheContents = gzcompress($contents, $this -> gzLevel);
}
else
{
$cacheContents = $contents;
}
if ($file = @fopen($this -> cachePath, 'w'))
{
fwrite($file, $cacheContents);
fclose($file);
}
else die ($this -> errors[0]);
print $contents;
}
}
class LambdaHTTPCache
{
private $lastModified; //The last-modified time of the document
private $proxy = 'Public'; //The proxy option (public or private)
private $userAgent = FALSE;
//The errors which may be displayed
private $errors = array (
'The $time parameter must be an integer');
//Public methods
public function __construct () { }
public function checkTime ($time) //This method checks if this time is bigger than the last-modified time
{
if (!is_int($time)) die ($this -> errors[0]);
elseif ($time > $this -> lastModified) $this -> lastModified = $time;
}
public function setProxy ($private, $userAgent) //This method adds some parameters to use client proxies
{
if ($private == TRUE) $this -> proxy = 'Private';
if ($userAgent == TRUE) $this -> userAgent = TRUE;
}
public function sendHeaders () //This method sends the HTTP headers
{
$serverDate = gmdate('D, d M Y H:i:s', time());
$lastModifiedDate = gmdate('D, d M Y H:i:s', $this -> lastModified);
header('Date: '.$serverDate.' GMT');
header('Last-Modified: '.$lastModifiedDate.' GMT');
if ($this -> userAgent == TRUE) header ('Vary: User-Agent');
header('Cache-Control: '.$this -> proxy.', must-revalidate');
header('Pragma: '.strtolower($this -> proxy));
$requestDate = substr(@$_SERVER['HTTP_IF_MODIFIED_SINCE'],0,29);
if ($requestDate != '' AND strtotime($requestDate) == $this -> lastModified)
{
header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', TRUE, 304);
exit;
}
}
}