Forum Moderators: coopster

Message Too Old, No Replies

Easy PHP Caching

Simply and easy caching

         

eltreno

3:53 pm on Aug 4, 2005 (gmt 0)

10+ Year Member



HI All

I build a cms which produces standard front end dynamic pages which pull content from mysql, some of these pages have logged in specific infomation. (Pretty standard stuff)

So I just started to looking into caching and came across the script which seem to good to be true so I'm posting to see if you think this is a good way to cache my pages (that aren't the logged in ones of course).
This may be a very standard way of doing it but I just want to find out if anyone know why I should or should not use this method, It just sems to easy :)

Bacically it works with firstly including the first file which checks if cached version exists and sends it to buffer then exits if it doesn't.

Then the last script, if we get to it, simply writes the buffer to the cache dir ready for use on next request.

First included script, to be included at top of script to be cached


<?php

// Settings
$cachedir = '../cache/'; // Directory to cache files in (keep outside web root)
$cachetime = 600; // Seconds to cache files for
$cacheext = 'cache'; // Extension to give cached files (usually cache, htm, txt)

// Ignore List
$ignore_list = array(
'mysite.com/rss.php',
'mysite.com/search/'
);

// Script
$page = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // Requested page
$cachefile = $cachedir . md5($page) . '.' . $cacheext; // Cache file to either load or create

$ignore_page = false;
for ($i = 0; $i < count($ignore_list); $i++) {
$ignore_page = (strpos($page, $ignore_list[$i])!== false)? true : $ignore_page;
}

$cachefile_created = ((@file_exists($cachefile)) and ($ignore_page === false))? @filemtime($cachefile) : 0;
@clearstatcache();

// Show file from cache if still valid
if (time() - $cachetime < $cachefile_created) {

//ob_start('ob_gzhandler');
@readfile($cachefile);
//ob_end_flush();
exit();

}

// If we're still here, we need to generate a cache file

ob_start();

?>

second include script, to be included at bottom of your script to be cached

<?php

// Now the script has run, generate a new cache file
$fp = @fopen($cachefile, 'w');

// save the contents of output buffer to the file
@fwrite($fp, ob_get_contents());
@fclose($fp);

ob_end_flush();

?>

they also say keep cache dir you use above root dir fair enough

I have tested this and it works great
When I have a script that I want cached only when not loggin in for example, I just put if statements around the includes of these scripts to not cache when I don't want ie if a certain parameter is sent I know not to cache.

Is this standard/good way of caching can someone advice please.

Trent

DanA

4:16 pm on Aug 4, 2005 (gmt 0)

10+ Year Member



I use a similar script (yours seems better) for the html version of an RSS feed, I compare the dates of the cached file (create it if it doesn't exist) and the rss feed on the server. Thus I only have one script at the top of the page that outputs to the browser(and also to the cache if the file isn't there).

chrisjoha

6:07 am on Aug 5, 2005 (gmt 0)

10+ Year Member



I'm using something to the same effect. I'm doing it the oo way though, but the idea is basically the same.

prometeus

10:28 am on Aug 5, 2005 (gmt 0)

10+ Year Member



file: foocache.inc

<?php
/*************************************************************************/
/* Configuration */
/*************************************************************************/

//Where to store cache files? Webserver needs wirte access!
$foocache[cachedir] = $_SERVER[DOCUMENT_ROOT]."/cache";
//Maximum allowed age for cache files (in seconds)
$foocache[maxage] = 1*24*60*60; //one day
//Referencefile no cachefile may be older than that file
$foocache[reffile] = $_SERVER[DOCUMENT_ROOT].'/inc/recache';
//optional path to the tidy binary leave blank if you don't want it
$foocache[tidy] = $_SERVER[DOCUMENT_ROOT].'/cgi-bin/tidy';
//options for tidy you should use the second one if your input files are
//not in iso-8859-1 charset
$foocache[tidyopts] = "-m -i -wrap 0 --drop-empty-paras false -ascii --tidy-mark false";
//$foocache[tidyopts] = "-m -i -wrap 0 --drop-empty-paras false -raw --tidy-mark false";

//These tags are used when the optional query marking is used (see README)
$foocache[hi_in] = '<span style="background-color:#ffffcc">';
$foocache[hi_out] = '</span>';

/*************************************************************************/
/* License */
/*************************************************************************/

// This is free Software (GPL)
// see COPYING for details

/*************************************************************************/
/* No changes needed below */
/*************************************************************************/

function foocache_start(){
if (defined("NOFOOCACHE")) return;

global $foocache;
$foocache[ltime]=foocache_time();

//construct filename from requesturi and post params
$md5 = md5($_SERVER[REQUEST_URI].@join("",$_POST));
$file = $foocache[cachedir].'/'.$md5;

//valid cachedata available? load it and stop further processing
if( (file_exists($file)) &&
((time()-filemtime($file)) < $foocache[maxage]) &&
(filemtime($foocache[reffile]) < filemtime($file)) &&
(filemtime($file) > filemtime($_SERVER[SCRIPT_FILENAME])) ){
$data = join("",file($file));
//hilight query:
if(!empty($foocache[query])){
$data = foocache_hilight($data);
}
print $data;
$t = round(foocache_time() - $foocache[ltime],3);
print "\n<!-- foocache: site processed in $t sec (cache used) -->";
exit;
}
//no cachedata found start capturing output
ob_start();
}

function foocache_hilight($data){
global $foocache;
$in = $foocache[hi_in];
$out = $foocache[hi_out];
$queries = preg_split ("/\s/",$foocache[query],-1,PREG_SPLIT_NO_EMPTY);
foreach ($queries as $q){
$q = preg_quote($q,'/');
$data = preg_replace("/((<[^>]*)¦$q)/ie", '"\2"=="\1"? "\1":"${in}\1${out}"', $data);
}
return $data;
}

function foocache_stop(){
if (defined("NOFOOCACHE")) return;
global $foocache;

//construct filename from requesturi and post params
$md5 = md5($_SERVER[REQUEST_URI].@join("",$_POST));
$file = $foocache[cachedir].'/'.$md5;
//get contents from the outputbuffer
$data = ob_get_contents();
$length = ob_get_length();
//flush the outputbuffer and stop capturing
ob_end_clean();
//write the cachefile
fwrite(fopen("$file", "w"),$data,$length);

$log = $foocache[cachedir].'/tidy.err';
//try to tidy the cachefile
if(is_executable($foocache[tidy])){
system("$foocache[tidy] $foocache[tidyopts] -f $log $file");
}

//get the cachefile
$data = join("",file($file));

//hilight query:
if(!empty($foocache[query])){
$data = foocache_hilight($data,$foocache[query]);
}

//print the cachefile
print $data;

$t = round(foocache_time() - $foocache[ltime],3);
print "\n<!-- foocache: site processed in $t sec (no cache used) -->";

//clean up and delete all other old cache files
foocache_cleanup();
}

function foocache_touch(){
global $foocache;
fwrite(fopen($foocache[reffile], "w"),"touched");
}

function foocache_time(){
list($usec, $sec) = explode(" ",microtime());
return ((float)$usec + (float)$sec);
}

function foocache_cleanup(){
global $foocache;

$handle = opendir($foocache[cachedir]);
while ($file = readdir ($handle)) {
$file = $foocache[cachedir].'/'.$file;
if(is_dir($file)) continue;
if( is_file($file) &&
(
( (time() - filemtime($file)) > $foocache[maxage] ) ¦¦
( filemtime($foocache[reffile]) > filemtime($file) )
)
)
{
unlink($file);
}
}
closedir($handle);
}

?>

Now you can start it from your page.
<?
require "./inc/foocache.inc";
foocache_start();
?>

and stop it
<?
foocache_stop();
?>

eltreno

3:36 pm on Aug 5, 2005 (gmt 0)

10+ Year Member



Excellent

Thanks Guys