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, ...).
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:
[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.
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:
$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:
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.
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:
[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.
Since 1.13, this provider supports the SimpleCacheKey class to identify a dedicated cache item.
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:
[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.
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:
[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.
Since 1.13, this provider supports the SimpleCacheKey class to identify a dedicated cache item.
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:
[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:
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.
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:
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:
$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
}
}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:
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.
Using the ApcCacheProvider you can store content request-independently within an APC Shared Memory Segment since release 1.17.
In order to use the provider the following configuration section must be created:
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 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:
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:
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.
JetBRAINS supports the development of the APF with PHPStorm licenses and we feel confidential that PHPStorm strongly influences the APF's quality. Use PHPStorm!
Proud to useIntelligent PHP IDE for coding, testing and debugging with pleasure