Zend Certified Engineer

phpguru.org

Free PHP, Javascript and C# code

Caching with PHP5

Question: Whats the best way to improve performance of your website?
Answer: Get rid of it, and stop worrying.

Unfortunately, that's not always practical (livelihoods etc). So lets have a look at caching instead. Rather miraculously I've just written and published some nifty caching code.

The code is PHP5 only, and built with a static class mindset. This kinda uses the OOP system as namespaces, though also uses inheritance to reuse common code. The code is separated out into three classes, Cache, OutputCache and DataCache. Groups and unique IDs are used to identify individual cached content. This comes in handy if you have to clear just a certain section of the cached data.

The Cache class is the base class, and contains common code for generating filenames, and reading and writing data files. Most of the code here is protected, as you shouldn't be interfacing with this class directly except in one instance, which is enabling or disabling the cache.

Output Cache

The OutputCache class is used for caching the generated output of your scripts, or certain sections of them. It has Start and End methods, and is used like this:

<?php
    
    
if (!OutputCache::Start("myGroup", "myID", 600)) {
    
        
// Generate some output (as you do)...
    
        
OutputCache::End();
    }
    
?>

So whats happening here? Well first off the call to Start() passes the group, unique ID and the TTL (Time To Live) for this particular bit of caching. So the data will be uniquely identified on disk by the group/id combo, and will be considered stale after the TTL number of seconds have passed. This function returns true if the data is found in the cache, and also prints the data to the screen. This means the code inside the if() block is skipped (thanks to the not (!) operator), and so the data isn't printed twice.

If however, the given combo of group/id isn't found in the cache, the Start() method will return false. When this happens output buffering is turned on to record the output. The code inside the if() block will then run (again - the not (!) operator), generate the output (which gets buffered), and then call the End() method. This method stops output buffering, saves the data to disk, and then prints it.

Elegant, efficient, and sexy. What more could you ask for?

Data Cache

The DataCache is used to cache data structures, as opposed to script output. This allows you to cache the creation of large arrays for example, or the results of slow queries. This is helpful if your pages are rather dynamic, though some areas aren't. Or in a recently experienced situation of mine: You have one central DB server, and multiple front end webservers. A common setup. If the load is getting high on the database, you might want to move some portion of queries (ORDER BY RAND() is a good example) to the webservers instead of the database server. Thus randomisation (eg using shuffle()) happens on one of 5 webservers, instead of your single resource limited database server. Anyway, some code:

<?php
    
    
if (!$data = DataCache::Get("myGroup", "myOtherID")) {
    
        
$result = $db->query("SELECT BIG_ASS_QUERY()");
        
        
DataCache::Put("myGroup", "myOtherID", 600, $result);
    }
    
    
// Do something useful with $result
    
?>

So in this example (very similar to output caching), if the data is cached, it's assigned to $data and the if() block is skipped. If not, then the if() block is run, and the data is cached at the Put() method call.

Miscellaneous Bits

There's a few configuration bits and bobs you can twiddle with if you like twiddling. setPrefix() as you can well imagine sets the prefix used in the cache data filenames. This defaults to "cache_". setStore() sets where the data files themselves are stored. This defaults to "/dev/shm/", since this is a convenient way to store the data files in shared memory. If you don't have this, try changing the path to "/tmp/". Must be given with a trailing slash.

And last, and least (so as not to be a corny ass), there's the static variable Cache::$enabled. That's how your refer to static class variables in case you didn't know. This is a boolean which enables or disables the cache. Surprising that.

C'est tout. Get the code here.

Link to me

If you use any of the code on this site (and if you don't I guess) or it makes your life easier, I'd appreciate a link - http://www.phpguru.org. Thanks.

RSS Feed for Comments

Comments

Author: Dumitru MIHAI
Posted: 4th April 2005 18:19
You are a true GURU !
Best Regards,
Dumitru MIHAI
Quote
Author: Richard Heyes
Posted: 5th April 2005 22:24
Dumitru MIHAI:
> You are a true GURU !

Ta very much.
Quote
Author: Leo
Posted: 17th August 2005 19:04
Very useful code indeed! Thank you!
Quote
Author: Richard Heyes
Posted: 8th September 2005 19:43
Cats Muvva:
> You get this month's paw-print of approval from
> me, Gormless George and the Three Suspects.

Is that a good thing? ;-)
Quote
Author: James
Posted: 31st October 2005 17:24
This is very similar to my general-purpose Cache class. I use it for query results, native PHP types and user-defined objects, PHP-generated HTML, and GD-generated thumbnails.
Quote
Author: MX
Posted: 2nd December 2005 16:30
How about using MemCache PECL extension?
Quote
Author: Tony
Posted: 13th February 2006 02:25
I think you have a typo in your DataCache exmaple. Shouldn't the
if (!$data = DataCache::Get("myGroup", "myOtherID"))
be
if (!$result = DataCache::Get("myGroup", "myOtherID")) {

Thanks for the code. works great!!

Quote
Author: Mislav
Posted: 18th February 2006 12:21
Your code is excellent, much better than other caching libraries (even Cache_Lite), but I felt that your API could be better. So I've completely rewritten the API and sprinkled some tiny extra functionality.

Mail me if you want me to send it to you, I will be glad to. In a few days I will connect it to my HTTP-cache class so we could have both server and browser caching out-of-the-box.
Quote
Author: Team
Posted: 7th April 2006 16:25
This a great help! Thank you. We will try to add a few more functions static instance creation and internal logging of caches produced in a give script.

Ps: April 9 Amazon will ship you a something from your wishlist.

Thanks again.
Quote
Author: Gilles
Posted: 25th July 2007 15:00
Richard, good job. How about combining this with HTTP/304 status codes so you have one general cache instruction? Could you please contact James/Mislav and ask them if they could share their code?
Quote

Post Comment

Your name:
Your email:
(Don't worry, I won't spam you.)
Comments:
  Do not post support type questions please

 
CAPTCHA image If you can't read the CAPTCHA then press the submit button to get another. Your comment will re-appear (as if by magic...).
Captcha image
Last modified: 16:24 29th December 2006