Jump to content

Browser Caching dynamic content using PHP output buffer and ETag


mikerowe81

Recommended Posts

I have been researching some strategies to optimize a web application I am working on particularly related to web browser caching and dynamic data. Since potentially the same dynamic content may be loaded multiple times in a session, I came up with the following method using PHP's output buffer and using a hash of the content as an ETag.

 

I realize that the only thing I really save with this method is the transfer of data back to the user since the PHP script still has to completely run, but I was curious if anyone has done something similar and if there are any thoughts or concerns I should be aware of or what other methods may be better.

 

Here is the code I am including at the top of each page:

 

<?php
function hash_buffer($content) {
$buffer_hash = crc32($content);
if ($_SERVER['HTTP_IF_NONE_MATCH'] == $buffer_hash) {
 header('HTTP/1.1 304 Not Modified');
 header("ETag: $buffer_hash");
 return '';
}
header('Cache-Control: private, no-cache');
header("ETag: $buffer_hash");
return $content;
}


ob_start('hash_buffer');
?>

Link to comment
Share on other sites

Depends on what kind of content it is you're serving up on what kind of caching you might do.  If you can reliably determine a last modified date, then do that.  For example if you were serving up blog posts you might update the timestamp any time the blog is modified.  In such a case, you can use that to generate a Last-Modified header to send with the page.  When a url is requested you could check for a $_SERVER['HTTP_IF_MODIFIED_SINCE'] header and do a quick check before actually rendering the blog post out.  Eg:

 

<?php
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
   $lastModified = queryDbForLastModifiedDateOnly();
   if (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified){
      header('HTTP/1.1 304 Not Modified');
      exit;
   }
}

$blogData = queryDbForBlogData();
header('Last-modified: '.$blogData['lastModifiedDate']) //Lookup the proper date format.
echo $blogData['contents'];
exit;

 

 

For an etag approach you could do a hash of the contents of the page or some set of data that you need to know if it's changed or not.  In the blog example above rather than checking a last modified time you could just hash the $blogData['contents'] and use that as an etag.

 

The potential problems to something like this comes from if you change the sites layout but not any of the content.  The cache check wouldn't recognize that since it only checks the content.  You could get around that by having an indicator of the last time the layout has changed, such as maybe a layout version # or last changed date that you include in in the cache check.  Eg:

define('LAYOUT_VERSION', '1.0'); //In a global config file somewhere

 

$etag = crc32(LAYOUT_VERSION.$content); //to generate the tag

 

Changing either the content or the version would cause the etag value to change.

 

Link to comment
Share on other sites

Kicken,

 

Thanks for the response. I did consider the last-modified-date, but my content isn't as conducive to that option like your blog example.

 

I am working on a Student Information System, so most of the content will change pretty regularly, which I know kind of defeats the effectiveness of caching, but things like a course's student lists and assignment lists should solidify as a semester progresses thus increasing its effectiveness.

 

I could see where hashing just the content I am concerned about might save some processing, but that would also mean I would need to define what content to hash on each page. The beauty of using the output buffer was I can include the same script on every page knowing that the final output would be hashed and compared just before it is sent.

 

The other aspect of my project I probably should have mentioned was that most of the content is AJAX driven, so that allows me to separate my layout which would be cached independently of my content.

 

Thanks again for your insights, that has helped me thing through some other aspects of this.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.