Caching

Allikas: Juhised

With popularity comes more page request, and with more page requests comes higher server load. Don't get in a situation where you can't serve up the pages. Build your application to handle the load. That's where PEAR::Cache comes in.

A PHP script must be compiled and processed by the Zend engine regardless if its results are the same each time it's called. The server needs to work harder to generate and display the requested page as your PHP applications become more complex. As your web site attracts more visitors, the server works harder more often. The server's performance may eventually begin to degrade.

If it's known that the output will be the same each time a script will be run, there's no need for the server to reprocess it. The load on the server can be reduced if the output of such scripts are stored and returned later for matching requests. This storing is known as caching.

Caching is not a new idea; caching exists in web browsers, proxy servers and other special applications. In PHP, we can reap the benefits of caching output in our scripts by using Pear::Cache.

The Cache package is dependant upon a few other PEAR packages. It needs HTTP_Request which in turn is dependent upon Net_URL which in turn is dependent upon Net_Socket. Obviously there are some packages that must be installed prior to using Cache.

The code part we need to write looks like this:

  1. 		$options = array (
  2. 			'cache_dir' => dirname(__FILE__) . '/cache'
  3. 		);
  4.  
  5. 		require_once 'Cache.php';
  6. 		$cache = new Cache('file', $options);
  7.  
  8. 		$idReminding = $cache->generateID('reminding');
  9.  
  10. 		if (!($data = $cache->get($idReminding)))
  11. 		{
  12. 			require_once dirname(__FILE__) . '/haldus/kasutajad/User.php';
  13.  
  14. 			User::getUsersToSendReminders();
  15.  
  16. 			$cache->save($idReminding, 'reminding', REMINDING_INTERVAL);
  17. 		}

Pear::Cache can be made available to our PHP scripts simply by including Cache.php - line 5.:

Pear::Cache is flexible in that it can cache script results in various ways, such as databases, files and even shared memory. We will pass two arguments when we create an instance of the cache object: the storage type and an array of options (line 6).

Valid storage options are: db, dbx, file, mdb, msession, phplib and shm. We will be storing our cached results as files.

Each storage mechanism accepts different parameters. The valid options for storing cached data as files are: cache_dir, filename_prefix and max_userdata_linelength.

The cache_dir option enables us to specify the directory where we want our cached files to be stored.

The filename_prefix enables us to specify a prefix to add to each cached file generated. This allows us to keep our cache organized while still keeping all cache files in the same directory. It also provides us a way to work around any clashing IDs when we use the generateID method discussed later.

The max_userdata_linelength is used to specify how much the class' fgets function will read at a time when retrieving cached data. max_userdata_linelength is used primarily for the sake of efficiency.

While of course you are welcome to experiment with the various options, we won't use filename_prefix or max_userdata_linelength. We will keep things simple and set just the directory used to house our cached files (lines 1-3).

The generateID method creates an md5 hash based on a given value. The hash can be used to identify the cached script results and is passed to the get and save methods when retrieving and storing the data (line 12).

The save method accepts a minimum of two arguments: the ID and the contents to store in the cache. However, information that changes must be regenerated and recached. A number representing the length of time for which the cached information is to be considered valid may be passed as a third argument (the time is measured in seconds). For example, our example caches information with a shelf-life of the given seconds in REMINDING_INTERVAL.

If the cached data's life is not set then it will never expire.

The get method accepts an ID and returns the cached content if it exists. If the content does not exist or has expired it will return NULL (line 10). In such a case, we need to reset the cache content (line 16). In our example, we use the cache for reminding intervals and remind only when the cache is expired (lines 12-14).