How to Displaying an RSS feed with PHP
Introduction
Whether you are retrieving information from a database or grabbing news headlines from another site, properly used caching can help reduce the run time of your PHP scripts and load on your server. Aside from the speed considerations, caching can also add dependability. By caching results from your database queries, you can still use the results in the event your database goes down.
Today we will look at a class designed to do caching, but first, let’s determine when we should use caching.
When to cache
Before you just start caching data, you need to determine if the data should be cached.
The first thing to assess is how often the data changes. If the data you are thinking about caching changes frequently, it may not be a good candidate. There’s not much point in caching if you have to refresh the cache every couple of minutes.
The prime candidate for caching is data that does not continually change, or data that it would be acceptable to show a stale version of until the next time the cache is refreshed.
You also need to establish how often the data is accessed. Caching content that is rarely viewed is not worth the overhead of the caching process. Ideally, we want to cache data that is accessed frequently, as the point of caching is to reduce the load on our data source.
Typical Uses
There are many different situations in which caching can be effective. I will outline a couple of uses here, and I invite you to add your comments to this article with ways you have put caching to use.
Category Listings
Many websites have a drop down boxes with category listings in them, such as departments for an online store. These categories are normally very static. Rather than hit a database and pull the categories on every page load, it makes sense to cache the data for extended periods of time. Caching this type of data for several hours, or even days is fairly common.
News Listings
News is an item that can be updated fairly frequently but can still benefit greatly from caching. Most sites that offer news have a window in which the news is occasionally updated but the rest of the time is static. By caching this type of data you may display some stale data, but the performance gain should more than makeup for it.
Statistics
All types of statistics are displayed on web sites today. Generally, it is not critical that the data is completely current. Caching this type of data, and giving it a relatively low expire time, can result in significant performance gains.
Caching Class
Now we will take a look at a class designed to do caching for us. It is comprised of three functions, Set
, Get
, and Delete
.
Set Function
void Set($varId, $varValue)
The Set the
function takes a variable id and value as arguments. You can define the variable id as anything you wish, but remember this is the identifier that you will access the cached variable with. The Set
function first calls the Delete
function. Then, it writes the serialized value to a file.
Get Function
mixed Get($varID, $cacheLife)
This function receives the variable id and a cache life as arguments. The cache life should be specified in seconds or left blank if you want to use the default value. The function attempts to locate a cached variable identified by the variable id. If it finds a file that matches the naming convention, it will determine if it is within the cache life. If the cache file can not be found or is out of life, the function will return false. Otherwise, it will return the value that was cached.
Delete function
void Delete($varId)
The Delete
the function accepts the variable id as its argument. This function simply unlinks any cache files associated with the variable id.
Code Flow
For the purposes of this article, I will place the class in a file named cacher.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php class Cacher { /* Where things are cached. * must have trailing slash! */ var $cacheDir = "/tmp/"; /* How long to cache something for in seconds */ var $defaultCacheLife = "3600"; /* Set($varId, $varValue) -- * Creates a file named "cache.VARID.TIMESTAMP" * and fills it with the serialized value from $varValue. * If a cache file with the same varId exists, Delete() * will remove it. */ function Set($varId, $varValue) { /* Clean up old caches with same varId */ $this->Delete($varId); /* Create new file */ $fileHandler = fopen ($this->cacheDir . "cache." . $varId . "." . time (), "a"); /* Write serialized data */ fwrite ($fileHandler, serialize ($varValue)); fclose ($fileHandler); }<code class="tutorialExample"> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /* Get($varID, $cacheLife) -- * Retrives the value inside a cache file * specified by $varID if the expiration time * (specified by $cacheLife) is not over. * If expired, returns FALSE */ function Get($varId, $cacheLife="") { /* Set default cache life */ $cacheLife = (!empty ($cacheLife)) ? $cacheLife : $this->defaultCacheLife; /* Loop through the directory looking for cache file */ $dirHandler = dir ($this->cacheDir); while ($file = $dirHandler->read()) { /* Check for cache file with requested varId */ if (preg_match ("/cache.$varId.[0-9]/", $file)) { /* Cache filename array */ $cacheFileName = explode (".", $file); /* Cache file creation time */ $cacheFileLife = $cacheFileName[2]; /* Full location */ $cacheFile = $this->cacheDir . $file; /* Check to see if cache file has expired or not */ if ((time () - $cacheFileLife) < $cacheLife) { $fileHandler = fopen ($cacheFile, "r"); $varValueResult = fread ($fileHandler, filesize ($cacheFile)); fclose ($fileHandler); /* Still good, return unseralized data */ return unserialize ($varValueResult); } else { /* Cache expired, break loop */ break; } } } $dirHandler->close(); return FALSE; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* Delete($varId) -- * Loops through the cache directory and * removes any cache files with the varId * specified in $varID */ function Delete($varId) { $dirHandler = dir ($this->cacheDir); while ($file = $dirHandler->read()) { if (preg_match ("/cache.$varId.[0-9]/", $file)) { /* Delete cache file */ unlink ($this->cacheDir . $file); } } $dirHandler->close(); } } /* end class */ ?> |
Example Use
- Include cacher.php
- Instantiate an object of the class
- Try and get a cached version of the data
- If a cache does not exist, get the data from the data source and cache it.
- Do something with the data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?php include ("cacher.php"); $cache = new Cacher; $variable = $cache->Get("var1", 60); if (!$variable) { /** Cache file expired or doesn't exist. Do something to get new result. **/ mysql_connect ('localhost','user','pass'); mysql_select_db ('db'); $result = mysql_query ('SELECT * FROM table'); while ($newresult[] = mysql_fetch_assoc ($result)); $cache->Set("var1", $newresult); $variable = $newresult; } print_r ($variable); ?> |
Conclusion
I would like to point out that caching is not always the best solution. Make sure you understand what you are caching and when. Test with and without caching and determine for yourself what provides better results.
When used properly, caching can take an enormous load off your server. If used improperly, it can add additional load to it.