Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    New to the CF scene
    Join Date
    Apr 2006
    Location
    Greece
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Post Caching with PhP

    Introduction

    In this article I will try to give a view of what is the custom caching with php, why and how we can use it.

    In the modern days, most of the sites are database driven. That means that your site is actually an application which retrieves data from a DBMS ( database managment system, eg MySQL) , parses the data and shows the result to the user. Most of these data are usually don't change frequently or don't change at all, and the reason that we use the database is that we can easilly update the site and the content.

    A problem that this process creates is the server overhead. Every time we execute a query in the 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 especcially for sites with heavy traffic is a real big problem.

    How we can solve this problem?

    There are two ways to solve this if you want to make your site faster. First is optimizing the queries, but we will not talk about this at the present article. The second and most valuable is using some kind of custom caching technique.

    Custom caching with php

    First let me explain the idea behind custom caching. When we have dynamic pages that their data is not updated frequently, we can use a 'system' that will be able to create the page, and then store it for later use. That means that after the page's creation, our application will not run the queries again in order to display the page, but it will show the cached one. Of course this system must be able to keep the cached pages for a time period that we will set.

    Let's code it

    Here is a simple class that will do the job. Let's see the code first :

    PHP Code:
    <?php
    class cache
    {
        var 
    $cache_dir './tmp/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()
        {
            
    //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($handle8192);
                    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 );
            }
        }
    }


    //Example :
    $ch = new cache();
    echo 
    date("D M j G:i:s T Y");
    $ch->close();
    ?>
    Now let me explain :

    function cache()

    This is the constructor function of the class. The job of this function is to check if there is a cached file for the page that we want, or it should create it. Here is how this is done :

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

    This line creates the file name of our cached page. So the cached file will be something like /path/to/cache/dir/request_uri

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

    Here we check if there is a cached version of this page, and if the file must be recreated because it has expired. If the file is cached, it will show the cached page and the exit. I will explain later why exit. If the cached file must be created this code will be executed :

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

    The first statement indicates to the close() function that it is creating the cache file, and the ob_start() will start buffering the output. The buffer's data will be used later by the close() function to save the cache file.

    function close()

    This function must be called from the end of your script, and it will do the rest of the job. Actually it is needed only when we are in the process of caching that's why it starts with the statement if ( $this->caching )
    Let me explain what is happening here :

    $data = ob_get_clean();

    Here we get all the data from the output buffer while we unset it, and put the data in the $data variable. The four statements that folow up are showing the data and then write the cache file.

    Troubleshooting

    This is a very simple class, and the purpose is to learn how you can implement a caching solution for your site. The obligation using this class is that you must use it only in this form :

    PHP Code:
    <?php
     $a 
    = new cache();
     ....
     ....
     ....
     
    $a->close();
    ?>
    If you have code after the $a->close() statement, the class will not work right. This is because of the exit() statement in the cache() function.

    Of course you can take this code and make it work for your own needs.

    A quick solution is to remove the exit() statement in the cache() function and then use the class this way :

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

    Hope this helped.


    You can publish this article to your site, but only if you give back a link to http://www.webdigity.com/

  • #2
    raf
    raf is offline
    Master Coder
    Join Date
    Jul 2002
    Posts
    6,589
    Thanks
    0
    Thanked 0 Times in 0 Posts
    don't get me wrong: i'm not trying to put you down or so, but i'm quite this form of caching has much use with db-driven sites. for almost all sites, the content simply wount be static enough + the performancegain will not be noticable.

    did you ever benchmark if this indeed results into any significant performancegain?
    in comparison then with a fully db-driven website with an optimized db and that uses recordset-buffering? pulling data from a db goes so fast, that it usually takes up just a few percent of the total responsetime. the db-load is almost never the bottleneck, unless you're talking about generating complex reports on huge amounts of static data (like in an OLAP tool that runs on historic data). but then there are better ways, like pre-generating these reports and storing them as html or pdf files.
    i honestly don't think there are a lott of db-driven sites where the content is static enough + the db-load is so high that caching is required to optimize performance.
    if you're in a situation where you indeed need to get that extra bit of performance, then PHP was probably a bad choice and then you'd better used a lower-level language.
    Posting guidelines I use to see if I will spend time to answer your question : http://www.catb.org/~esr/faqs/smart-questions.html

  • #3
    New to the CF scene
    Join Date
    Apr 2006
    Location
    Greece
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts
    This type of caching can be usefull to high demand sites with tons of visitors, but smaller sites can use it to have a better response.

    About the benchmarks, I have tested it in a working server, and it had good results. The first page to served delays a little, but the rest will be served very fast.

    This job is incredible fast on pages that use string queries instead of numeric ones (I know this is wrong anyway, but it may be needed for some reason) and in general for pages that use delayed queries (eg. the stats from adsense or any other statistical program)

  • #4
    Senior Coder
    Join Date
    Oct 2003
    Location
    Australia
    Posts
    1,963
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Along very similar lines is the PEAR class Cache Lite.
    I've had good results with the above class and also found it trivial to implement on existing codebases.

    I take no responsibility for the above nonsense.


    Left Justified

  • #5
    New Coder
    Join Date
    May 2007
    Posts
    23
    Thanks
    0
    Thanked 0 Times in 0 Posts
    This worked nicely the example time would cache for the amount of time I set it to but once that time was reached it would never recache it, just update ever page load after that time

  • #6
    Senior Coder kbluhm's Avatar
    Join Date
    Apr 2007
    Location
    Philadelphia, PA, USA
    Posts
    1,509
    Thanks
    3
    Thanked 258 Times in 254 Posts
    I have nothing against info caching, but the only real good use I've ever found for it is saving shared info between numerous user sessions.

    For instance, if I'm pulling content from an API, RSS feed, etc -- some type of remote information that could cause a performance hit if retrieved with each page load -- and the visitors are coming more frequently than the content changes.

  • #7
    New Coder
    Join Date
    May 2007
    Posts
    23
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I have a page that pulls info from a very large database and is accessed by thousands of users a day I only need that data updated daily so this would work perfect form me if I can get it resolved, Currently if I set it to cache for 5 minutes for testing for the first 5 minutes it shows me the cached version but after five minutes it doens't re-cache for 5 minutes instead it will run the queries everytime I load the page after the initial first 5 minutes

  • #8
    Regular Coder anarchy3200's Avatar
    Join Date
    Mar 2003
    Location
    England
    Posts
    261
    Thanks
    0
    Thanked 1 Time in 1 Post
    Just been playing with this script recently and encountered the same problems as previously commented on that the cache does not update after the first run.
    This is caused by a cache of the file information being created so the last access time that is used to check whether the file is recently cached is always the same.
    This can be corrected by using the function
    Code:
    clearstatcache()
    If you add this in at the start of the cache() function i.e.
    PHP Code:
    function cache() 
        { 
            
    //Constructor of the class 
            
    clearstatcache();
            
    $this->file $this->cache_dir urlencode$_SERVER['REQUEST_URI'] );
    ... 
    Then it resolves this problem.

    Don't know whether it was just me but also encountered intermittant problems using fileatime, although easilly rectified with filectime instead which achieves the same goal...

    PHP Code:
    if ( file_exists $this->file ) && ( filectime $this->file ) + $this->cache_time ) > time() ) 
    Hope this helps.
    Last edited by anarchy3200; 08-09-2007 at 01:03 AM.
    Mike

  • #9
    New Coder
    Join Date
    May 2007
    Posts
    23
    Thanks
    0
    Thanked 0 Times in 0 Posts
    thanks you very much thats works well for me now, no 1 other problem I would like the save this class into a file and be able to set the time when calling the function, so it can be different times for different pages, any idea how to do?


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •