CacheManager

The CacheManager itself 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.

In order to easily address any kind of cache item release 1.13 introduced so called CacheKeys. These are complex keys consisting of any kind of attributes that can be used to load and save cache items (simple strings, objects, lists, ...).

1. Configuration

The CacheManager expects the configuration file cacheconfig.ini within tools::cache namespace. For each cache manager, one configuration section must be present in the configuration containing the following directives at minimal:

APF configuration
[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. Therefore, the CacheManagerFabric features the getCacheManager() method, that creates the desired cache manager corresponing to the configuration section. Hence, the fabric is 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}'); // for releases < 1.13 $cacheKey = 'my_cache_key'; $cacheContent = $cM->getFromCache($cacheKey); // for releases >= 1.13 $cacheKey = new SimpleCacheKey('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.

Release 1.13 introduces two more providers, that can handle complex cache keys. The AdvancedTextCacheProvider thus enhances the TextCacheProvider and the AdvancedObjectCacheProvider enables the AdvancedTextCacheProvider to store any kind of PHP objects. Details can be taken from the chapters 3.5 and 3.6.

3.1. Text cache provider

The text cache provider implements a simple filesystem-based caching component. Threrefore, the cache is saved to the configured base folder with an advanced file system structure designed for good performance. The main folder is named as the first two characters of the md5 checksum of the cache key the sub folders are named as the entire hash key.

To use this provider, the referenced configuration section must look like this:

APF configuration
[text_cache] Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "TextCacheProvider" Cache.Active = "" Cache.BaseFolder = "" Cache.Namespace = "" [Cache.FolderPermission = "0770"]

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 separated by "::" to create the desired subfolder structure.

The optional Cache.FolderPermission configuration directive can be used to define the file permission mask for cache folders that are created by the provider.

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

Since 1.13, this provider supports the SimpleCacheKey class to identify a dedicated cache item.

Since release 1.17 the TextCacheProvider also supports usage of the AdvancedCacheKey.

3.2. Object 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 configuration
[object_cache] Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "ObjectCacheProvider" Cache.Active = "" Cache.BaseFolder = "" Cache.Namespace = "" [Cache.FolderPermission = "0770"]

The optional Cache.FolderPermission configuration directive can be used to define the file permission mask for cache folders that are created by the provider.

Since 1.13, this provider supports the SimpleCacheKey class to identify a dedicated cache item.

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 configuration
[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.

To use the MemCacheProvider, the PHP extension memcache must be loaded!

Since 1.13, this provider supports the SimpleCacheKey class to identify a dedicated cache item.

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 configuration
[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:

SQL statement
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.

Since 1.13, this provider supports the SimpleCacheKey class to identify a dedicated cache item.

3.5. Enhanced text cache provider

The implementation of the AdvancedTextCacheProvider supports more complex cache keys and is intended to store cache elements that have several favours. This is necessary for an HTML cache for example, where different results (e.g. for different urls) for the same page must be stored. Nevertheless, the possibility to clear the entire content of the page or just parts of it must be given.

In order to use this provider, the following configuration section must be created:

APF configuration
Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "AdvancedTextCacheProvider" Cache.Active = "" Cache.BaseFolder = "" Cache.Namespace = "" [Cache.FolderPermission = "0770"]

The optional Cache.FolderPermission configuration directive can be used to define the file permission mask for cache folders that are created by the provider.

Please note the next code box to see how to read and write complex cache items:

PHP code
$pageId = /* ... */; $currentUrl = $_SERVER['REQUEST_URI']; // create cache key, that stores the cache for one page but with different flavours $cacheKey = new AdvancedCacheKey($pageId, $currentUrl); // load cached content $content = $cM->getFromCache($cacheKey); if($content === 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 } }

3.6. Enhanced object cache provider

The AdvancedObjectCacheProvider enhances the AdvancedTextCacheProvider to save serialized objects in the cache. But the structure and the usage of the provider is the same. To read and write cache items, the AdvancedCacheKey must be used.

In order to use this provider, the following configuration section must be created:

APF configuration
Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "AdvancedObjectCacheProvider" Cache.Active = "" Cache.BaseFolder = "" Cache.Namespace = "" [Cache.FolderPermission = "0770"]

The optional Cache.FolderPermission configuration directive can be used to define the file permission mask for cache folders that are created by the provider.

3.7. APC cache provider

Using the ApcCacheProvider you can store content request-independently within an APC Shared Memory Segment since release 1.17.

Use the ApcCacheProvider to decrease the I/O access of your application and thus speed it up.

In order to use the provider the following configuration section must be created:

APF configuration
Cache.Provider.Namespace = "tools::cache::provider" Cache.Provider.Class = "ApcCacheProvider" Cache.Active = "" Cache.Namespace = "" [Cache.ExpireTime = ]

Since the cache resides within the RAM of the web server only the Cache.Namespace must be specified.

Using the Cache.ExpireTime parameter tha validity of cache entries can be controlled. In case any limitation is needed, please fill this parameter with the desired validity time - beginning at creation or updating date of the cache entry - in seconds. In case the parameter is not set, cache entries are kept until the server is restarted.

Reading, saving, and deletion just works as with all the other providers described above.

The ApcCacheProvider both supports the usage of the SimpleCacheKey as well as the AdvancedCacheKey. Hence, you can create complex cache structures as desired.

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. Each provider implements the three methods read(), write() and clear() of the CacheProvider interface.

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 getConfigAttribute() function can be used. Therefore it is necessary to derive from CacheBase. Applying the name of the attribute, the method returns the content of the given directive. For operating purposes, the method throws an exception, if the attribute is not existing or empty. Details can be taken from the API definition for the class on the downloads page.

The cache keys are represented by dedicated data types since release 1.13. The scheme is described by the CacheKey interface. The APF ships the implementations SimpleCacheKey and AdvancedCacheKey.

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 CacheBase implements CacheProvider { public function read(CacheKey $cacheKey){ } public function write(CacheKey $cacheKey, $object){ } public function clear(CacheKey $cacheKey = null){ } }

The return values are described in the API documentation of the CacheProvider interface. 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 equal within this provider.

The code box below gives you an idea, how a cache provider for image resources could look like:

PHP code
class PNGImageCacheProvider extends TextCacheProvider { public function read(CacheKey $cacheKey){ $cacheFile = $this->getCacheFile($cacheKey); if(!file_exists($cacheFile)){ return null; } else{ return createimagefrompng($cacheFile); } } public function write(CacheKey $cacheKey, $object){ $cacheFile = $this->getCacheFile($cacheKey); FilesystemManager::createFolder(dirname($cacheFile)); imagepng($object,$cacheFile); } public function clear(CacheKey $cacheKey = null){ if($cacheKey === null){ $baseFolder = $this->getConfigAttribute('Cache.BaseFolder'); FilesystemManager::deleteFolder($baseFolder,true); } else{ $cacheFile = $this->getCacheFile($cacheKey); FilesystemManager::removeFile($cacheFile); } } }

In case the cache keys shipped with the release do not suffice the requirements of the newly implemented provider, the cache key implementations SimpleCacheKey and AdvancedCacheKey can be enhanced according to the CacheKey interface.

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.