Wednesday, 21 March 2012

Caching Tutorial in PHP

Caching Tutorial For Beginners


In the old days most of the websites were designed in static manner which means that the pages and contents

doesn't get updated automatically, one has to change the content via coding to update contents of pages.

But then dynamic web pages came into existance and introduce problem.

Your site is actually an application which retrieves data from DBMS, parses the data and shows the result to

the user. Most of the data don't change frequently or don't change at all, and the reason we use database is

that we can easily update the content of the site.

But the problem with this is that it increses the server overhead. Everytime we execute a query in database,

the instance of our script will call the DBMS, and then the DBMS will send the results of the query. This is

time consuming and especially for complex site with heavy traffic is a real big problem.

This is where cachiong can help us out, instead of regenerating the page everytime, the scripts running this

site generate it the first time they're asked to, then store a copy of what they send back to your browser.

The next time a visitor requests the same page, the script will know it'd already generated one recently and

simply send that to the browser without re-running database queries or searches.

For example "News" section of any website updates on a daily basis so it makes sense to have it in a database

rather than as a static file so it can be easily updated and searched.

The Idea Behind Custom Caching

when we have dynamic pages whose data doesn't get updated frequently, we can use a 'system' that will be able

to create the page, and the store it for later use. After page's cretion our system will not run the queries

again in order to display the pages, but it will show the cached one.

Following is a simple class that will do it:

Code:
<?php
class cache_class
{
    var $cache_dir = './cache/';//This is the directory where the cache files will be stored;
    var $cache_time = 1000;//How much time will keep the cache files in seconds.
   
    var $caching = false;
    var $file = '';

    function cache_class()
    {
        //Constructor of the class
        $this->file = $this->cache_dir . urlencode( $_SERVER['REQUEST_URI'] );
        if ( file_exists ( $this->file ) && ( fileatime ( $this->file ) + $this->cache_time ) > time() )
        {
            //Grab the cache:
            $handle = fopen( $this->file , "r");
            do {
                $data = fread($handle, 8192);
                if (strlen($data) == 0) {
                    break;
                }
                echo $data;
            } while (true);
            fclose($handle);
            exit();
        }
        else
        {
            //create cache :
            $this->caching = true;
            ob_start();
        }
    }
   
    function close()
    {
        //You should have this at the end of each page
        if ( $this->caching )
        {
            //You were caching the contents so display them, and write the cache file
            $data = ob_get_clean();
            echo $data;
            $fp = fopen( $this->file , 'w' );
            fwrite ( $fp , $data );
            fclose ( $fp );
        }
    }
}
?>

Here is a small implementation of this class:

<?php

    include_once "cache/cache_class.php";
    date_default_timezone_set('Asia/Calcutta');
    $ch = new cache_class();
    echo date("Y/m/d");
    $ch->close();

?>

Now I will discuss above functions:

function cache_class()

This is the constructor function of this class. Its job is to check whether the cached file for the page that

we want is already existing, or it should recreate it. Here is how it is done:

$this->file = $this->cache_dir . urlencode( $_SERVER['REQUEST_URI'] );

This line creates the file name of our cached page.

if ( file_exists ( $this->file ) && ( fileatime ( $this->file ) + $this->cache_time ) > time() )

Here we will check if the cached version of this page is existing, and if the file must be recreated because

it's expiration. If the file is cached it will show the cached file. If the cached file must be created this

code will be executed:

$this->caching = true;
ob_start();


function close()

This function must be called at the end of the script, and it will do the rest of the job. Let me explain waht

is happening here:

$data = ob_get_clean();

Here we can get all the data from the output buffer while we unset it, and put the data in the $data variable.

The follow up statements above are showing the data and then write the cache file.

        This is a very simple class, and the purpose is to learn how you can implement a caching

solution for your site. But you can only use this class in this form:

Code:
<?php
 $a = new cache_class();
 ....
 ....
 ....
 $a->close();
?>


If there is some code after $a->close() statement, the class will not work right. This is because of the

exit() statement in the cache_class() function.

Solution to remove the exit() statement in the cache_class() function and then use the class this way:

Code:
<?php
 $a = new cache_class();
 if ( $a->caching )
 {
 ....
 ....
 ....
 }
 $a->close();
?>





Happy Coding :) :) :)


Nitin Jaiswal
Finelogics Consulting

1 comment:

  1. Is it ok to use fileatime or filemtime will be ideal? I tested your code in my projects. fileatime is not working properly (working fine for 1st time, but after the 1st cache time period, the cache file is updated everytime). But I just change fileatime with filemtime, and it is working ok now. In some opensource like joomla they also used filemtime in cache section.

    ReplyDelete