CacheManager

As you can take from the Roadmap, the 1.8 branch contains a redesigned cache manager. The old dated implementation had various disadvantages while using the cache classes or extend them, respectively.

Hence, the new implementation is much more convenient but yet powerful due to the easy extension API. The CacheManager itself only deals with the creation and configuration of the concrete CacheProvider implementations, that present the write, read and clear capabilities. The release already contains common providers and an abstract provider definition that allows you to enhance the list of providers easily.


1. Configuration

The CacheManager expects a configuration file within the tools::cache namespace and the current application's context. The name of the config file is cacheconfig. For each cache manager, one configuration section must be present in the configuration containing the following directives:
APF-Konfiguration
[my_cache_instance] Cache.Provider.Namespace = "" Cache.Provider.Class = "" Cache.Active = ""
The Cache.Provider.Namespace parameter defines the namespace of the provider implementation, Cache.Provider.Class contains the class name and Cache.Active defines the activity state of the cache manager. In case, the configuration directive contains "true", the cache manager is considered active, otherwise not.

Please note, that each provider expects some more configuration attributes, described in the following chapters.


2. Usage

The cache manager design includes the possibility to create several cache manager instances within one application or one module. For this reason, a factory is used to create the cache managers. Therefor, the CacheManagerFabric features the getCacheManager() method, that creates the desired cache manager corresponing to the configuration section. Hence, the fabrix ist created via the service manager, the fabric is a singleton to not slow down the performance of the component due to several initialisation processes. Caching components have to be fast per se!

The following code box provides a typical application sample:
PHP-Code
$cMF = &$this->__getServiceObject('tools::cache','CacheManagerFabric'); $cM = &$cMF->getCacheManager('{config_section}'); $cacheKey = 'my_cache_key'; $cacheContent = $cM->getFromCache($cacheKey); if($cacheContent === null){ $cacheContent = /* generate content */; $cM->writeToCache($cacheKey,$cacheContent); } // clear cache if necessary if(/* ... */){ if(/* ... */){ $cM->clearCache($cacheKey); // clean only the desired cache content } else{ $cM->clearCache(); // clean the entire namespace } }
As you can see, the cache manager has three API methods, that delegate the functionality to the corresponding provider, that is currently used:
  • getFromCache(): Reads the desired cache content. If no content is available for the given cache key, null is returned. This can be used to check, if a cache entry exists at the same time.
  • writeToCache(): Writes the desired content to namespace configured within the configuration section. The method returns true on success, otherwise false.
  • clearCache(): The clearCache() method can be used to maintain the cache. If no cache key is provided during function call, the entire namespace is purged, if a key is present, the cache content for this key is deleted.


3. Included provider

The framework already includes four ready-to-use provider. These are aimed to solve common caching issues. If there is not provider fitting your requirements, an own provider can be implemented as described in chapter 4.


3.1. Text cache provider

Der Text-Cache-Provider implementiert ein einfaches Filesystem-Caching. Hierbei wird unter einem definierten Basis-Pfad der gewünschte Cache-Inhalt strukturiert abgelegt. Als erstes Strukturelement wird der Namespace eingesetzt, gefolgt von einem weiteren Unterordner aus den ersten beiden Zeichen des md5-Schlüssels des Cache-Keys.

To use this provider, the referenced configuration section must look like this:
APF-Konfiguration
[text_cache] Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "TextCacheProvider" Cache.Active = "" Cache.BaseFolder = "" Cache.Namespace = ""
Cache.BaseFolder contains the cache base folder, that is managed by the CacheManager, the attribute Cache.Namespace names the namespace, that is the first structural element within the base folder. Please note, that the sections of the namespace must be seperated by "::" to create the desired subfolder structure.

Note: The text cache provider uses the FilesystemManager for cache folder management. For this reason, the user that is assigned to the webserver, must habe write permissions to the base folder.


3.2. Objekt cache provider

The object cache provider is based on the text cache provider described under section 3.1. As of the text cache provider, the cache files are also stored on the filesystem. The difference is, that this provider serializes the objects presented to the cache manager before storing them within a cache file. This mechanism enables the developer to create a filesystem based object cache.

To use the provider, the following directives have to be included in the configuration section:
APF-Konfiguration
[object_cache] Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "ObjectCacheProvider" Cache.Active = "" Cache.BaseFolder = "" Cache.Namespace = ""

3.3. Mem cache provider

The memcache provider gives you the opportunity to store PHP objects within a memcached server. To make the objects storable, they are serialized whilst saving and unserialized when retrieving from the cache. Please note, that resource types cannot be serialized and have to be reinitialized on unserialize.

To access a memcached, the following configuration section must be provided:
APF-Konfiguration
[mem_cache] Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "MemCacheProvider" Cache.Active = "" Cache.Host = "" Cache.Port = "" Cache.PersistentConnect = "" Cache.Namespace = ""
Despite the fact, that the PHP memcache functions do not support namespaces within the memcache cache keys, the MemCacheProviders supports namespaces. This is realized by the internal cache key management. This renders possible to clear all cache keys within one namespace as described in the above code sample.

Note: To use the MemCacheProvider, the PHP extenstion memcache must be loaded!


3.4. Database cache provider

The DBCacheProvider uses a database table to store the cache information. In order to use the database as a cache backend, the configuration section should look like this:
APF-Konfiguration
[database_cache] Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "DBCacheProvider" Cache.Active = "" Cache.Connection = "" Cache.Table = "" Cache.Namespace = ""
Thereby, Cache.Connection specifies the database connection key, that is used to create a database connection with the ConnectionManager. For this reason, a corresponding database connection configuration must be provided as described in the ConnectionManager's class reference.Cache.Table defines the name of the cache table, that should be created with the statement below:
Code
CREATE TABLE `database_cache` ( `CacheID` int(5) NOT NULL auto_increment, `namespace` varchar(100) NOT NULL default '', `cachekey` varchar(100) NOT NULL default '', `value` text NOT NULL, PRIMARY KEY (`CacheID`), KEY `cachevalues` (`namespace`,`cachekey`) );
Allow me to call your attention to the fact, that the columns namespace, cachekey and value must be named as printed above.


4. Enhancement

The design of the cache manager includes several components. The creation of the desired cache manager instance is done by the CacheManagerFabric. This component creates, initializes and manages the concrete CacheManager instances. The cache manager itself deals with the initialization of the desired provider and features the interface methods described in chapter 2. Thus, each provider implements the three abstract methods read(), write() and clear() of the AbstractCacheProvider class. These functions is given the desired cache key and the cache content as desired. To access the configuration params defined in the dedicated section, the private __getCacheConfigAttribute() function can be used. Applying the name of the attribute, the method returns the content of the given directive. For operating purposes, the method triggers an error, if the attribute is not existing or empty. Details can be taken from the API definition for the class on the downloads page.

Thanks to the fact, that a provider is addressed by it's namespace and class name, an own provider can be stored where ever you want. The body of a application specific provider looks like this:
PHP-Code
class MyCacheProvider extends AbstractCacheProvider { function MyCacheProvider(){ } function read($cacheKey){ } function write($cacheKey,$content){ } function clear($cacheKey = null){ } }
The return values are described in the API documentation of the AbstractCacheProvider class. If the functionality of existing providers should be used, you can easily inherit from the desired provider. This is already used within the ObjectCacheProvider, because the cache folder and cache file name generation is also used within this provider.

The code box below gives you an idea, how a cache provider for image ressources could look like:
PHP-Code
class PNGImageCacheProvider extends TextCacheProvider { function PNGImageCacheProvider(){ } function read($cacheKey){ $cacheFile = $this->__getCacheFile($cacheKey); if(!file_exists($cacheFile)){ return null; } else{ return createimagefrompng($cacheFile); } } function write($cacheKey,$img){ $cacheFile = $this->__getCacheFile($cacheKey); FilesystemManager::createFolder(dirname($cacheFile)); imagepng($img,$cacheFile); } function clear($cacheKey = null){ if($cacheKey === null){ $baseFolder = $this->__getCacheConfigAttribute('Cache.BaseFolder'); FilesystemManager::deleteFolder($baseFolder,true); } else{ $cacheFile = $this->__getCacheFile($cacheKey); FilesystemManager::removeFile($cacheFile); } } }

Comments

Do you want to add a comment to the article above, or do you want to post additional hints? So please click here. Comments already posted can be found below.
There are no comments belonging to this article.