Cache is a programming concept that can be used in a various range of applications and for various purposes. A cache library can be used for storing database queries for later use, to store rendered pages to be served again without generating them again, or to save indexed pages in a crawler application to be processed by multiple modules.

    A cache mechanism is more simple that it might sound. It’s just a simple module that should implement 2 actions:
  • to store a value(identified by a key).
  • to retrieve a value if it’s not expired.
  • additionally it can offer a mechanism to invalidate a set of values or the entire cache.

In this tutorial we are going to create a disk cache script. It stores the string values in files, each value is stored in a file and it contains an additional file to store the expiration date. Performance wise, this is not the best approach, but the script is designed like that with a clear purpose: the additional file can be used to store additional attributes, beside the expiration date. Imagine an application that crawls pages, with different modules. Each time a module crawls the page, it adds it’s result to the additional file.

The cache library in our tutorial is based only on a few functions grouped in a single class. Let’s start with the skeleton of the SimpleCache class:

class SimpleCache
{
	public function exists($key)
	{
	}

	public function get($key)
	{
	}

	public function put($key, $content)
	{
	}
}

Once we have the skeleton class, we create a test class:

// SimpleCacheTest.php - file to test the class
require_once "SimpleCache.php";

// instantiate the class
$cache = new SimpleCache();

// cache a value
$cache->put('key', 'this value');

// retrieved the cached value by key
$val = $cache->get('key');

// assert the retrieved value
if ($val != 'this value')
     echo 'Something went wrong!';
else
     echo 'Value as expected. Cache Test Passed';
    In the next step we add variables to the class, for configuration:

  • the location where the cache files are stored. The location can be an absolute one or relative to the starting point of the script(in the code above is the cache subdirectory, located in the same directory where index.php is invoked from).
  • the expiry interval in which the cache values expire.
class SimpleCache
{
	private $cacheDir = 'cache';
	private $expiryInterval = 2592000; //30*24*60*60;

	public function setCacheDir($val) {  $this->cacheDir = $val; }
	public function setExpiryInterval($val) {  $this->expiryInterval = $val; }
	...
}

Then we implement the put function. The code is very simple: we create the path if it doesn’t exist, then we we write the data in the main cache file and the expiration interval in the additional file:

	public function put($key, $content)
	{
		$time = time(); //Current Time

		if (! file_exists($this->cacheDir))
			mkdir($this->cacheDir);

		$filename_cache = $this->cacheDir . '/' . $key . '.cache'; //Cache filename
		$filename_info = $this->cacheDir . '/' . $key . '.info'; //Cache info

		file_put_contents ($filename_cache ,  $content); // save the content
		file_put_contents ($filename_info , $time); // save the time of last cache update
	}

The method to retrieve the code is pretty simple. We try to read the expiry time from the additional file. If it exists and the data is not expired we read the content of the cache file and return it:

	public function get($key)
	{
		$filename_cache = $this->cacheDir . '/' . $key . '.cache'; //Cache filename
		$filename_info = $this->cacheDir . '/' . $key . '.info'; //Cache info

		if (file_exists($filename_cache) && file_exists($filename_info))
		{
			$cache_time = file_get_contents ($filename_info) + (int)$this->expiryInterval; //Last update time of the cache file
			$time = time(); //Current Time

			$expiry_time = (int)$time; //Expiry time for the cache

			if ((int)$cache_time >= (int)$expiry_time) //Compare last updated and current time
			{
				return file_get_contents ($filename_cache);   //Get contents from file
			}
		}

		return null;
	}

We create an additional function to check the existence of valid data in cache, similar to get function, in case we need to check it without reading it:

	public function exists($key)
	{
		$filename_cache = $this->cacheDir . '/' . $key . '.cache'; //Cache filename
		$filename_info = $this->cacheDir . '/' . $key . '.info'; //Cache info

		if (file_exists($filename_cache) && file_exists($filename_info))
		{
			$cache_time = file_get_contents ($filename_info) + (int)$this->expiryInterval; //Last update time of the cache file
			$time = time(); //Current Time

			$expiry_time = (int)$time; //Expiry time for the cache

			if ((int)$cache_time >= (int)$expiry_time) //Compare last updated and current time
			{
				return true;
			}
		}

		return false;
	}

Now that the code was written it can be testes using the test file. In a next tutorial we are going to rewrite this cache mechanism using the file modify date time instead of the additional time.

Did you enjoy this tutorial? Be sure to subscribe to the our RSS feed not to miss our new tutorials!
... or make it popular on