Home arrow PHP arrow Page 2 - Implementing a Cache System in PHP

Building Multiple Cache Back-ends in PHP - PHP

In this programming tutorial, you will learn how to create a simple caching system using a PHP segregated interface.

TABLE OF CONTENTS:
  1. Implementing a Cache System in PHP
  2. Building Multiple Cache Back-ends in PHP
  3. Cache Data in RAM with PHP
By: Alejandro Gervasio
Rating: starstarstarstarstar / 4
June 08, 2011

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement


Building a couple of implementers of the previous “CacheableInterface” interface is a pretty straightforward process. As I expressed before, the first cache back-end that I want to show you is a simple wrapper for the APC PHP extension, and its source code is as follows:

(ApcCache.php)

<?php

class ApcCache implements CacheableInterface
{
    /**
     * Save data to the cache
     */
    public function set($key, $data)
    {
        if (!apc_store(strtolower($key), $data)) {
            throw new ApcCacheException('Error saving data with the key ' . $key . ' to the APC cache.');
        }
        return $this;
    }
   
    /**
     * Get the specified data from the cache
     */
    public function get($key)
    {
        if ($this->exists($key)) {
            if (!$data = apc_fetch(strtolower($key))) {
                throw new ApcCacheException('Error fetching data with the key ' . $key . ' from the APC cache.');
            }
            return $data;
        }
        return null;
    }
   
    /**
     * Delete the specified data from the cache
     */
    public function delete($key)
    {
        if ($this->exists($key)) {
            if (!apc_delete(strtolower($key))) {
                throw new ApcCacheException('Error deleting data with the key ' . $key . ' from the APC cache.');
            }
            return true;
        }
        return false;
    }
   
    /**
     * Check if the specified cache key exists
     */
    public function exists($key)
    {
        return (boolean) apc_exists(strtolower($key));
    }
   
    /**
     * Get cache information
     */
    public function getInfo()
    {
        ob_start();
        print_r(apc_cache_info());
        return ob_get_clean();
    }
    
    /**
     * Clear the cache
     */
    public function clear($cacheType = 'user')
    {
        return apc_clear_cache($cacheType);
    }       
}



(ApcCacheException.php)

<?php

class ApcCacheException extends Exception{}

In the above code snippet, the “ApcCache” class acts like a proxy for the most relevant methods included in the APC extension, which allows you to store, fetch and delete data from shared memory. The class is pretty similar to the one that I developed in this previous article (http://www.devshed.com/c/a/PHP/Swapping-Cache-BackEnd-at-Runtime-in-PHP/), so if you had the chance to read the tutorial, understanding how this cache back-end works should be a breeze for you.

Now, take a look at the following class, which also implements the “CacheableInterface” interface, only this one caches data using the file system:

(FileCache.php)

<?php

class FileCache implements CacheableInterface
{
    protected $_cacheDir = 'cache';
   
    /**
     * Constructor
     */
    public function __construct($cacheDir = '')
    {
        if ($cacheDir !== '') {
            if (!is_dir($cacheDir)) {
                throw new FileCacheException('The specified cache directory is invalid.');
            }
            $this->_cacheDir = $cacheDir;
        }
    }
   
    /**
     * Save data to the specified cache file
     */
    public function set($key, $data)
    {
        $cacheFile = $this->getCacheFile($key);
        if (!file_put_contents($cacheFile, serialize($data))) {
            throw new FileCacheException('Error saving data with the key ' . $key . ' to the cache file.');
        }
        return $this;
    }
   
    /**
     * Get data from the specified cache file
     */
    public function get($key)
    {
        if ($this->exists($key)) {
            $cacheFile = $this->getCacheFile($key);
            if (!$data = unserialize(file_get_contents($cacheFile))) {
                throw new FileCacheException('Error reading data with the key ' . $key . ' from the cache file.');
            }
            return $data;
        }
        return null;
    }
   
    /**
     * Delete the specified cache file
     */
    public function delete($key)
    {
        if ($this->exists($key)) {
            $cacheFile = $this->getCacheFile($key);
            if (!unlink($cacheFile)) {
                throw new FileCacheException('Error deleting the file cache with key ' . $key);
            }
            return true;
        }
        return false;
    }
   
    /**
     * Check if the specified cache file exists
     */
    public function exists($key)
    {
        $cacheFile = $this->getCacheFile($key);
        return file_exists($cacheFile);
    }
   
    /**
     * Get the specified cache file
     */
    protected function getCacheFile($key)
    {
        return $this->_cacheDir . DIRECTORY_SEPARATOR . strtolower($key) . '.cache';
    }     
}



(FileCacheException.php)

<?php

class FileCacheException extends Exception{}

This file-based back-end caches data in a specified file, located under the default “cache” directory (although this option can be easily changed). In addition, the class is capable of retrieving and deleting cache files as well, in accordance to the contract set by the “CacheableInterface” interface.

At this point, you saw how easy is to spawn a couple of cache back-ends based on the mentioned interface. Given that, the last thing that needs to be done to get this sample cache system up and running is create an adapter capable of consuming the previous cache classes via dependency injection.

The following class implements this adapter in a simple way:

(Cache.php)

<?php

class Cache
{
    protected $_cacheBackend;
   
    /**
     * Constructor
     */
    public function __construct(CacheableInterface $cacheBackend)
    {
        $this->_cacheBackend = $cacheBackend;
    }
   
    /**
     * Save data to the cache
     */
     public function set($key, $data)
     {
         $this->_cacheBackend->set($key, $data);
         return $this;
     }
    
     /**
     * Get data from the cache
     */
     public function get($key)
     {
         return $this->_cacheBackend->get($key);
     }
    
     /**
     * Delete the specified cache data
     */
     public function delete()
     {
         return $this->_cacheBackend->delete($key);
     }         
}


So far, so good. Having built a basic adapter that uses the “Plug-in” pattern to work with the previous cache back-ends (or eventually any other, as long as it implements the “CacheableInterface” interface), the last step that must be taken is set up an example that shows how to utilize this cache system.




 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: