Fugitive Thought

Login | Register | RSS | Help

FTCache - PHP Generic Caching Library - How-To

small logo

What Can Be Cached?

We can cache any object thing that PHP can serialize and that implements the FTCache_Cacheable interface. The interface contains a single method named getIndex() that returns an integer. The cache system uses this integer to identify the object, so it should be unique to the object we are caching. If two objects have the same return value for this, the cache system will assume that they are the same object.

Instantiating the Cache

You have 3 options to consider when instantiating an FTCache object:

  1. Size - number of entries that the cache will store. You can make this arbitrarily large without affecting the size of the cache under most containers if you do not use the full size. This simply limits how large the cache can grow to be.
  2. Strategy - this is the algorithm that maps the id of the object (return value of getIndex()) to the index of the cache entry it will be stored as. For example, if Size is 5, then the algorithm will map any return value of getIndex() to a value between 0 and 4 inclusive. Different strategies affect which cache entries get overwritten by new entries.
  3. Container - this is what handles where the data (contents of the cache) are actually stored. For example, two of the containers included with the library by default are Volatile and CSV. The volatile container stores the cache entries in an array, while the CSV container stores the entries in a CSV file on the disk. Depending on the container chosen, there will be limitations. For example, the Volatile container cannot store entries between runs of the script, since the array will be unset when the script completes each time. The CSV container can store persistent data since it will be able to re-open the file again later.

We will review the details of different strategies and containers later on. For now, this is an example of how to instantiate the cache using the DirectMapping strategy and the Volatile container on a cache with a maximum of 50 entries:

		require_once 'FTCache.php';
		
		$cache = new FTCache(50, 'DirectMapping', 'Volatile');
	

The above code will instantiate a new cache with a maximum of 50 entries stored in a Volatile container and mapping the objects into the container using the DirectMapping strategy. This format is the easiest, but has the limitation that it uses all of the default values for both the DirectMapping strategy and the Volatile container. For these two, this is not important, since they really have no other options. However, if we want to instantiate a CSV container with something other than the default options, we will need a different approach. An alternative instantiation technique is like this:

		require_once 'FTCache.php';
		
		$container = new FTCache_Container_Volatile(75, 'my_cache.csv', false);
		$strategy = new FTCache_Strategy_DirectMapping(75);
		$cache = new FTCache(75, $strategy, $container);
	

The above code sets up a CSV container with a maximum size of 75, stores it into the file named 'my_cache.csv', and tells the container NOT to clear the file on instantiation. By putting a false here, we allow ourselves to have a persistent container: we can access the data stored in it between runs of the program. We also use a DirectMapping strategy again, and tell it that the maximum size is 75. Finally, we instantiate the cache, tell it the size is 75 and give it the two objects we created. IMPORTANT: make sure that the size provided to the container, the strategy, and the cache are all the same value!

You can mix and match these two instantiation techniques. For example, if we just wanted the default options on the strategy (as we do in this example) then we could do this:

		require_once 'FTCache.php';
		
		$container = new FTCache_Container_Volatile(75, 'my_cache.csv', false);
		$cache = new FTCache(75, 'DirectMapping', $container);
	

Strategy and Container Selection

For an overview of the differences between different supported strategies, go to strategies page. You can do the same for the containers page. If you want to create custom containers or strategies, you can do so by creating a new class that extends FTCache_Strategy for an strategy, or FTCache_Container for a container. If you have one that you think might be useful to someone else, please email it to me at justin@fugitivethought.com and I'll review it, and probably add it to the official library.

Using the Cache

For the rest of this tutorial we will assume that you have some variable $cache that is an instantiation of FTCache. Let's also create some class named Test that we can use to demonstrate how the caching works.

		// Example cacheable object for testing purposes
		class Test implements FTCache_Cacheable {
			public $_id;
			public $_name;
			public $_system;
			public $_height;
		
			public function __construct($id, $name, $system, $height) {
				$this->_id = $id;
				$this->_name = $name;
				$this->_system = $system;
				$this->_height = $height;
			}
	
			public function getIndex() {
				return $this->_id;
			}
		}
	

This class is actually used in the Unit Tests to make sure that these steps work, so this tutorial should work completely every time and even with future changes. To see how the cache handles different objects we can do this:

		$a = new Test(4643, 'Justin', 'boo', 34);
		$b = new Test(954, 'Alex', 'foo', 72);
		$c = new Test(78651, 'John', 'hoo', 54);
		$d = new Test('bad', 'Alice', 'soo', 88);
		$e = new Test(684, 'Susan', 'moo', 61);
	

The only real anomaly in this set of objects is $d, which is instantiated with the id being equal to 'bad'. This object can be used to see how the system responds to invalid values of getIndex(), since getIndex() is supposed to always return an integer. First, if we add $a to the cache, we can get them back out. This will always be true of the Direct Mapping strategy. Other strategies may use some sort of logic to decide not to cache $a at all, in which case we will not be able to retrieve it again.

		// Add to cache
		$cache->set($a);
		
		// Retrieve it from the cache (4643 is the return value of $a->getIndex())
		$test = $cache->get(4643);
		
		// At this point $a and $test are basically the same thing. If you compare all of the
		// properties of both, they match. This will hold true for all public, private and
		// protected properties.
	

We can see the basics of how to send and retrieve data from the cache. We use 4643 to retrieve $a from the cache because 4643 is the unique identifier that $a uses to identify itself to the cache. If $a were not actually stored in the cache, then the value of $test at the end of this snippet of code would be FALSE. If we try to add something to the cache that does not implement FTCache_Cacheable, then the cache will throw an exception. If you want more details on what you expect for unusual cases, you can review the tests inside the full download from the downloads page.

The only other function of the $cache object is isCached($id). You can pass 4643 to isCached() and it will let you know whether that object is cached or not without trying to retrieve it. This would be faster to do then try to retrieve the object from the cache if the container you are using is slow at retrievals.

About Us | Site Map | Privacy Policy | Contact Us | ©2006 Justin DeMaris & Steven Maresca