Click here to Skip to main content
11,495,331 members (64,156 online)
Click here to Skip to main content

Tagged as

Caching HTML Output with PHP

, 26 Mar 2014 CPOL 4.1K 28 4
Rate this:
Please Sign up or sign in to vote.
How to cache HTML output with PHP

Introduction

There are many cases when people would like to create a cache for output of PHP pages on their website. This technique allows you to reduce a response time and increase productivity of your site. And, one of the important things, it's simple enough and may be used both for small sites and big web portals. It may also be very useful for code that performs a lot of "hard-time" operations, like: multiple database requests, long-time running of code parts, etc. In other words, it can be very helpful for site optimization.

The main idea behind this technique is that you catch the HTML output, generated by your PHP code (no matter what exactly you use: some PHP Framework or just plain coding), place this code in some file on your server and define the "life time" for this cache file. Now every time someone browses this page, your code checks if there is a cache available for a requested page and simply flushes to the screen a content of the stored cache file, stopping running the last part of the code. Of course, you have to check the "life time" of this cache file and if it was elapsed, you have to repeat the first steps again.

So.. on the first step, you have to create the directory where cache files will be stored, for example: cache/. Also, you have to prevent direct access and browsing of this directory. The simplest way to do this is to place in this directory .htaccess file with the following directive. For your cache files, you may define any extension you want: .html, .txt or something else; we prefer to use .chh as the cache file extension.

<FILES ~ "\.chh$">  
    Order allow,deny  
    Deny from all  
</FILES> 

Now, we create the first (top) part of the caching mechanism.

// get file name
$phpself = isset($_SERVER['PHP_SELF']) ? trim(basename($_SERVER['PHP_SELF']), '.php') : '';
// block access if unexpected characters found in file name 
if(preg_match("/:|;|'|\(|\)/", $phpself)) $phpself = '';

// define cache file name
$cachefile = ($phpself != '') ? 'cache/'.$phpself.'.chh' : '';

if(!empty($cachefile) && file_exists($cachefile)){
    // set lifetime in minutes
    $cachetime = 10 * 60; 
  
    // Serve from the cache if it is younger than $cachetime
    if((filesize($cachefile) > 0) &&
      ((time() - $cachetime) < filemtime($cachefile))){
        // the page has been cached from an earlier request
        // output the contents of the cache file
        include_once($cachefile); 
        echo '<!-- Taken from cache at: '.date('H:i', filemtime($cachefile)).' -->';
        // exit the script, so that the rest isn't executed
        exit;
    }        
}
// start the output buffer
ob_start(); 

Here is the second (bottom) part of this mechanism.

<?php
/* open the cache file for writing */
if(!empty($cachefile)){
    $fp = @fopen($cachefile, 'w'); 
    // save the contents of output buffer to the file
    @fwrite($fp, ob_get_contents());
    // close the file
    @fclose($fp);         
}
// Send the output to the browser
ob_end_flush();      
?>  

Now, we have to include both parts into your PHP file in the following way:

<?php include("cache_top.php"); ?>

<html>
<head>
    <title>Your Page</title>
</head>
<body>
    <h1>Header</h1>
    <p>here the content of your page</p>
</body>
</html>

<?php include("cache_bottom.php"); ?> 

How to Cache a File with Parameters?

// get file name
$phpself = isset($_SERVER['PHP_SELF']) ? trim(basename($_SERVER['PHP_SELF']), '.php') : '';
// block access if unexpected characters found in file name 
if(preg_match("/:|;|'|\(|\)/", $phpself)) $phpself = '';

// retrieve parameters
$page = isset($_GET['page']) ? $_GET['page'] : '';
$param1 = isset($_GET['param1']) ? $_GET['param1'] : '';
$param2 = isset($_GET['param2']) ? $_GET['param2'] : '';

// define cache file name
$cachefile = ($phpself != '') ? 'cache/'.$phpself.'-'.$page.'-'.$param1.'-'.$param2.'.chh' : '';

// Output
// cache/index-test-1-2.chh 
?>

Encoding File Names

Placing parameters in the cache file name is a good way to store them, but what to do if the value of parameter has characters, that are not acceptable in URLs? In this case, you can encode cache file name, using some encoding algorithms, for example md5.

<?php 

// get file name
$phpself = isset($_SERVER['PHP_SELF']) ? trim(basename($_SERVER['PHP_SELF']), '.php') : '';
// block access if unexpected characters found in file name 
if(preg_match("/:|;|'|\(|\)/", $phpself)) $phpself = '';

// retrieve parameters
$page = isset($_GET['page']) ? $_GET['page'] : '';
$param1 = isset($_GET['param1']) ? $_GET['param1'] : '';
$param2 = isset($_GET['param2']) ? $_GET['param2'] : '';

// define cache file name
$cachefile = ($phpself != '') ? 'cache/'.md5($phpself.'-'.$page.'-'.$param1.'-'.$param2).'.chh' : '';

// Output
// cache/25c9b35d591981b5324782dcd640eae5.chh
?> 

Now, when you check whether the cache file exists, you do this in the same way:

<?php

// get file name
$phpself = isset($_SERVER['PHP_SELF']) ? trim(basename($_SERVER['PHP_SELF']), '.php') : '';
// block access if unexpected characters found in file name 
if(preg_match("/:|;|'|\(|\)/", $phpself)) $phpself = '';

// retrieve parameters
$page = isset($_GET['page']) ? $_GET['page'] : '';
$param1 = isset($_GET['param1']) ? $_GET['param1'] : '';
$param2 = isset($_GET['param2']) ? $_GET['param2'] : '';

// define cache file name
$cachefile = ($phpself != '') ? 'cache/'.md5($phpself.'-'.$page.'-'.$param1.'-'.$param2).'.chh' : '';

if(!empty($cachefile) && file_exists($cachefile)){
    // set lifetime in minutes
    $cachetime = 10 * 60; 
  
    // Serve from the cache if it is younger than $cachetime
    if((filesize($cachefile) > 0) &&
      ((time() - $cachetime) < filemtime($cachefile))){
        // the page has been cached from an earlier request
        // output the contents of the cache file
        include_once($cachefile); 
        echo '<!-- Taken from cache at: '.date('H:i', filemtime($cachefile)).' -->';
        // exit the script, so that the rest isn't executed
        exit;
    }        
}
// start the output buffer
ob_start();   
?> 

Conclusion

In this tutorial, we've seen one of the possibilities that allows creating a caching mechanism for your website. Now, when you read this article and try to implement this knowledge to your own needs, you may be interested to check a response time of your site, if there are some improvements or not.

There are many resources on the Internet that may check the speed of your site, like http://developers.google.com or www.webpagetest.org.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

apphp
Founder ApPHP
United States United States
ApPHP.com founder, PHP Expert
http://www.apphp.com
Follow on   Twitter   Google+

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150520.1 | Last Updated 26 Mar 2014
Article Copyright 2014 by apphp
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid