PHP / ZendFramework: Using Zend_config together with ZendCache
ZendFramework provides a class to handle configuration: Zend_Config. It also provides a class to manage cache: Zend_Cache. But, unless the Zend_Translate component (as of the V1.7), Zend_Config does not natively support Zend_Cache. This article explains a solution.
1 – Classical usage of Zend_config:
1 2 3 |
//[...] $config = new Zend_Config_Ini('path/to/config.ini'); //[...] |
limits:
For big config files, this is a waste of time as the configuration file has to be parsed for each user’s query and application config files seldom changes. Adding a cache mecanism is a good way of optimizing this, but unlike Zend_Translate, Zend_Config does not provides a native support for Zend_Cache.
2 – Using Zend_Config with Zend_Cache transparently
2.1 problems / expectations
- caching the config file needs configuration parameters such as lifetime and cache path that cannot be put in configuration file itself => in this example, we use the session_save_path() as storage, which should be writable by php in most cases
- using Zend_Cache should be transparent to avoid bootstrap pollution => in this example we use a special configuration class on which only 1 static method call is needed to get a cached config object. Thus, using it does not add more code than typical Zend_config use as seen above
2.2 The proposed new way
Using this example’s class will make the code from chapter 1 to become the following:
1 2 3 |
//[...] $config = MyApp_Config::getInstance(); //[...] |
2.3 The Example class
2.3.1 Source code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
require_once 'Zend/Config/Ini'; require_once 'Zend/Cache'; /** * This class is used to retreive the application's configuration throught a static method. This * way, it is easy to use Zend_Cache to cache the whole configuration which seldom contains changes * @package MyApp */ class MyApp_Config { /** * full path to the configuration file */ const CONFIG_FILE = 'settings/application.ini'; /** * Cached instance of the configuration * @var Zend_Cache */ private static $_cache = null; /** * get the application's configuration * @return Zend_Config */ public static function getConfig() { return new Zend_Config_Ini(self::CONFIG_FILE,null); } /** * get the path for configuration cache (session's save path) * @return string */ public static function getConfigCachePath() { return session_save_path(); } /** * get an instance of the class (in fact a Zend_Config instance) * @return Zend_Config a cached instance of Zend_Config */ public static function getInstance() { // if never initialized, get a Zend_Cache instance if (!self::$cache) { self::$cache = Zend_Cache::factory('class', 'file', array('cached_entity' => 'MyApp_Config'), array('cache_dir' => MyApp_Config::getConfigCachePath())); } return self::$cache->getConfig(); } /** * clean the cache. A call to getInstance() must have been called once to make this work. */ public static function clearCache() { if (self::$cache) { self::$cache->clean(); } } } |
2.3.2 Remarks
- This example only works with file based caching (but it should not be difficult to adapt it to use others frontend)
- As we are caching the application’s configuration file itself, it is not really possible to store cache path in a configuration file (unless you would like the cached config system to use another config file itself… hmmm)
- This example is suitable for relatively biug config files. If you use little ones, you should do some benchmark to see if it provides any enhancement. I tested this code with a small config file (a dozen of entries) and the footprint was not perceptible using a profiler. So in all cases, this code should not add any overhead.
2.4 Cleanning up the cache
In case your config file changed and you don’t want to or can’t wait for the cache to expires, you can call the clearCache() method in a admin page or a special controller with some access restriction.
3 Conclusion
This was just a little example I wrote with my humble knowledges. It might be a starting point for more complexe configuration file architecture or for other caching mecanism (database, memcached, …)
Feel free to send me advices or remarks 😉