tags:

views:

323

answers:

4

Hello!

I have a PHP 5.1.0 website (actually it's 5.2.9 but it must also run on 5.1.0+).

Pages are generated dynamically but many of them are mostly static. By static I mean the content don't change but the "template" around the content can change over time.

I know they are several cache systems and PHP frameworks already out there, but my host don't have APC or Memcached installed and I'm not using any framework for this particular project.

I want the pages to be cached (I think by default PHP "disallow" cache). So far I'm using:

session_cache_limiter('private'); //Aim at 'public'
session_cache_expire(180);
header("Content-type: $documentMimeType; charset=$documentCharset");
header('Vary: Accept');
header("Content-language: $currentLanguage");

I read many tutorials but I can't find something simple (I know cache is something complex, but I only need some basic stuff).

What are "must" have headers to send to help caching?

Thanks!

A: 
<?php
header("Expires: Sat, 26 Jul 2020 05:00:00 GMT"); // Date in the future
?>

Setting an expiration date for the cached page is one useful way to cache it on the client side.

S Pangborn
Good, and using session_cache_limiter and session_cache_expire already taked care of this.
AlexV
A: 

Take your pick - or use them all! :-)

header('Expires: Thu, 01-Jan-70 00:00:01 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
Mike Foster
session_cache_limiter and session_cache_expire already control Expires, Cache-Control, Last-Modified and Pragma...
AlexV
I see. Yes, you are right. And I also see that I did not read your question well enough. sorry
Mike Foster
+1  A: 

You must have an Expires header. Technically, there are other solutions, but the Expires header is really the best one out there, because it tells the browser to not recheck the page before the expiration date and time and just serve the content from the cache. It works really great!

It is also useful to check for a If-Modified-Since header in the request from the browser. This header is sent when the browser is "unsure" if the content in it's cache is still the right version. If your page is not modified since that time, just send back an HTTP 304 code (Not Modified). Here is an example that works on Apache and sends a 304 code for ten minutes:

<?php
$headers = apache_request_headers();
if(isset($headers['If-Modified-Since'])) {
  if(strtotime($headers['If-Modified-Since']) < time() - 600) {
    header('HTTP/1.1 304 Not Modified');
    exit;
  }
}
?>

You can put this check early on in your code to save server resources.

Emil Vikström
+3  A: 

You might want to use private_no_expire instead of private, but set a long expiration for content you know is not going to change and make sure you process if-modified-since and if-none-match requests similar to Emil's post.

$tsstring = gmdate('D, d M Y H:i:s ', $timestamp) . 'GMT';
$etag = $language . $timestamp;

$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false;
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false;
if ((($if_none_match && $if_none_match == $etag) || (!$if_none_match)) &&
    ($if_modified_since && $if_modified_since == $tsstring))
{
    header('HTTP/1.1 304 Not Modified');
    exit();
}
else
{
    header("Last-Modified: $tsstring");
    header("ETag: \"{$etag}\"");
}

Where $etag could be a checksum based on the content or the user ID, language, and timestamp, e.g.

$etag = md5($language . $timestamp);
Steve-o