Speed Up Sites with php Caching  

Posted by T ZAMAN in

This explains the basic methods to get started caching with php headers

Article: http://www.w3.org/2005/MWI/BPWG/techs/CachingWithPhp

// $lastModifiedDate must be a GMT Unix Timestamp
// You can use gmmktime(...) to get such a timestamp
// getlastmod() also provides this kind of timestamp for the last
// modification date of the PHP file itself
function cacheHeaders($lastModifiedDate) {
if ($lastModifiedDate) {
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModifiedDate) {
if (php_sapi_name()=='CGI') {
Header("Status: 304 Not Modified");
} else {
Header("HTTP/1.0 304 Not Modified");
} else {
$gmtDate = gmdate("D, d M Y H:i:s\G\M\T",$lastModifiedDate);
header('Last-Modified: '.$gmtDate);

// This function uses a static variable to track the most recent
// last modification time
function lastModificationTime($time=0) {
static $last_mod ;
if (!isset($last_mod) || $time > $last_mod) {
$last_mod = $time ;
return $last_mod ;

implementing caching and 304 Not Modified handling

BTW if you are implementing sending gziped output it might be a good time to think about implementing caching and 304 Not Modified handling as well.

It is really easy.

A simple caching, zipping and If-Modified
handling script by Andreas Friedrich
$Id: cache.php,v 1.1 2002/07/16 14:45:06 af Exp $
$Name: $
$WEB_DEV_CACHE_DIR = '/var/www/html/www.ecotur.de//cache';

Check whether the UA sending the request supports gzip.

if (strpos($ACCEPT_ENCODING, 'gzip')!== false) $enc = 'gzip';
if (strpos($ACCEPT_ENCODING, 'x-gzip')!== false) $enc = 'x-gzip';

Build a unique filename for the requested file. You can use caching for slightly dynamic pages as well. Just include the variables that determine what is output in the array below.

Imagine a site that serves output depending on the UA string in the HTTP request header. For requests to a given URL we would need to store a file for each different UA in our cache.

$cached_file = '/var/www/html/www.ecotur.de//cache/'
. md5(implode('',
($sm? 'true' : 'fals'),
($ns4? 'true' : 'fals'),
($ns6? 'true' : 'fals'),
($moz? 'true' : 'fals'),
($op? 'true' : 'fals'),
($ie? 'true' : 'fals'),
($ie4? 'true' : 'fals'),
($ie5? 'true' : 'fals'),
($ie6? 'true' : 'fals'),
($linux? 'true' : 'fals'),
($mac? 'true' : 'fals'),
))) . '_' . $enc;

If the response needs to be handled by the main script as is the case if the UA send a cookie or posted some data or the cached file is invalid or does not exist we start output buffering and run the script. Then we write the output to disk.

if (count($_COOKIE)>0
or (!is_valid($cached_file))
or ($info = @stat($cached_file)) == false
) {
/* If there's no file or it's invalid we generate the output */
write_contents2cache($cached_file, $enc);

If-Modified Handling

If the UA sent a conditional request we check whether the cached file was changed since the time the UA supplied. If not we return a ‘HTTP/1.0 304 Not Modified’ status and exit the script.

/* Send 304 Not Modified if there were no
changes since last request */
$last = strtotime($info['mtime']);
$cond = isset($_SERVER['http_if_modified_since'])?
$_SERVER['http_if_modified_since'] : 0;
if ($cond and $_SERVER['REQUEST_METHOD'] == 'GET'
and strtotime($cond) >= $last) {
header('HTTP/1.0 304 Not Modified');

Now that we are sure a valid output file exists we send the appropriate header fields and then the actual file.

/* Output the file now that we are sure the file exists */
if ($enc) {
header("Content-Encoding: $enc");
$size = filesize($cached_file);
header("Content-Length: $size");

After sending the file we decide whether we want to keep the cached version or not. If it is highly dynamic (.i.e. uses cookies or posted data or contains a session id) we delete it.

if (isset($sessionid)
or isset($_COOKIE['authorid'])
or count($_COOKIE)>0) @unlink($cached_file);
if ($local) @unlink($cached_file);

It might be better to save the file to disk only after we decide we want to keep it. This will eliminate the time to access the hd and write and delete the file.

Hope this helps and is useful.


Use PHP to force a conditional GET

By examining $_SERVER['HTTP_IF_MODIFIED_SINCE'] if it is available. Consider the following function:

function conditionalGET($timestamp) {
$last-modified = gmdate("D, d M Y H:i:s \G\M\T", $timestamp);
$etag = '"'.md5($last-modified).'"';
header("Last-Modified: $last-modified");
header("ETag: $etag");
$if-modified-since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
$if-none-match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false;
if(!$if-modified-since && !$if-none-match) return;
if($if-none-match && $if-none-match != $etag) return;
if($if-modified-since && $if-modified-since != $last-modified) return;
header("HTTP/1.0 304 Not Modified");

To use the function, work out the timestamp for when the document was last modified and call the function with: conditionalGET($timestamp);

« HTTP Packet Capturing to debug ApacheApache Web Server Speed Configuration Hacks »
Get a Prepaid Visa Card - No credit check. Quick approval. Shop online, pay bills, use ATMs




This blog is intended for educational use. All data presented on this website were gathered from outside sources and no files are actually hosted in this website. The owner of this site shall not be held responsible for how the site visitors use the information provided here.


Top Commentators

Widget by Blogger Widgets

Recent Posts




FEEDJIT Live Traffic Feed