Article
Cache it! Solve PHP Performance Problems
How do I purge the Cache_Lite cache?
The built-in lifetime mechanism for Cache_Lite cache files provides a good foundation for keeping your cache files up to date, but there will be some circumstances in which you need the files to be updated immediately.
Solution
In cases in which you need immediate updates, the methods remove and clean come in handy. The remove method is designed to delete a specific cache file; it takes as arguments the cache ID and group name of the file. To delete the page body cache file we created in "How do I use PEAR::Cache_Lite for server-side caching?", we'd use this code:
$cache->remove('body', 'Dynamic');
If we use the clean method, we can delete all the files in our cache directory simply by calling the method with no arguments; alternatively, we can specify a group of cache files to delete. If we wanted to delete both the header and footer cache files we created in "How do I use PEAR::Cache_Lite for server-side caching?", we could do so like this:
$cache->clean('Static');
Discussion
The remove and clean methods should obviously be called in response to events that arise within an application. For example, if you have a discussion forum application, you probably want to remove the relevant cache files when a visitor posts a new message.
Although it may seem like this solution entails a lot of code modifications, with some care it can be applied to your application in a global manner. If you have a central script that's included in every page, your script can simply watch for incoming events--for example, a variable like $_GET['newPost']--and respond by deleting the required cache files. This keeps the cache file removal mechanism central and easier to maintain. You might also consider using the php.ini setting auto_prepend_file to include this code in every PHP script.
How do I cache function calls?
Many web sites provide access to their data via web services such as SOAP and XML-RPC. (You can read all about web services in Chapter 12.) As web services are accessed over a network, it's often a very good idea to cache results so that they can be fetched locally, rather than repeating the same slow request to the server multiple times. A simple approach might be to use PHP sessions, but as that solution operates on a per-visitor basis, the opening requests for each visitor will still be slow.
Solution
Let's assume you wish to create a web page that lists all the SitePoint books available on Amazon. The actual list is not likely to change from moment to moment, so why would we make the request to the Amazon web service every time the web page is displayed? We won't! Instead, we can take advantage of Cache_Lite by caching the results of the XML-RPC request.
Requires PEAR::SOAP Version 0.11.0
The following solution uses the PEAR::SOAP library version 0.11.0 to access the Amazon web service. You can find this package on the PEAR web site.
Here's some hypothetical code that fetches the data from the remote Amazon server:
$results = $amazonClient->ManufacturerSearchRequest($params);
Using Cache_Lite_Function, we can cache the results so the data returned from the service can be reused; this will avoid unnecessary network calls and significantly improve performance.
The following example code focuses on the caching aspect to prevent us from getting bogged down in the details of using the Amazon web service. You can see the complete script if you download this book's code archive from the SitePoint web site.
The Cache_Lite_Function requires the inclusion of the following file:
cachefunction.php (excerpt)
require_once 'Cache/Lite/Function.php';
We instantiate the Cache_Lite_Function class with some options:
cachefunction.php (excerpt)
$options = array(
'cacheDir' => './cache/',
'fileNameProtection' => true,
'writeControl' => true,
'readControl' => true,
'readControlType' => 'strlen',
'defaultGroup' => 'SOAP'
);
$cache = new Cache_Lite_Function($options);
It's important that the fileNameProtection option is set to true (this is in fact the default value, but in this case I've set it manually to emphasize the point). If it were set to false, the filename would be invalid, so the data will not be cached.
Here's how we make the calls to our SOAP client class:
cachefunction.php (excerpt)
$results = $cache->call('amazonClient->ManufacturerSearchRequest',
$params);
If the request is being made for the first time, Cache_Lite_Function will store the results as a serialized array or object in a cache file (not that you need to worry about this), and this file will be used for future requests until it expires. The setLifeTime method can again be used to specify how long the cache files should survive before they're refreshed; currently, the default value of 3600 seconds (one hour) is being used. You can then use the $results variable exactly as if you were calling the web service method directly. The output of our example script can be seen in Figure 11.1.
![]()
Summary
Caching is an important and often overlooked aspect of web site development. Many factors that affect the performance of today's web sites weren't a problem for their predecessors--from complex, dynamic page generation, to a reliance on third-party data over the network. In this chapter, we've examined HTML meta tags, HTTP headers, PHP output buffering and PEAR::Cache_Lite, and we've seen how you can use them to control the caching of your web site content and improve the site's reliability and performance.
Implementing a caching system for your site might be simple, but ultimately, it depends on your requirements. If you have a busy and predominantly static web site--such as a blog--that's managed through a content management system, it will likely require little alteration, yet may benefit from huge performance improvements resulting from a small investment of your time. Setting up caching for a more complex site that generates content on a per-user basis, such as a portal or shopping cart system, will prove a little more tricky and time consuming, but the benefits are still clear.
Regardless, I hope the information in this chapter has given you a good grasp of the options available, and will help you determine which techniques are most suitable for your application. Don't forget to download this chapter, plus two others -- PDO and Databases, and Access Control -- to enjoy offline. For information on the contents of the book's other chapters, check out the full Table of Contents.