Load Zend_Config_XML files using a cache

In a recent project I noticed that my configuration files where taking some ms of processing speed while parsing the xml files into Zend_Config object

To solve this problem, using a Cache is obvious, but there are more optimizations you need to consider when using Zend_Config

  • Zend_Config uses lots of in_array calls at each level you are investigating. So everytime you call for example $config->database->dbname, you are doing loads of in_array calls and other tests. Therefor you need to consider to convert Zend_Config instances into arrays (using Zend_Config::toArray) and use isset to test for deeper config settings
  • Split your configuration files into multiple files, and load the configurations only when actually required. There is no sense in loading(parsing/converting) your Zend_GData login credentials from your config, when you are only using those in one of your modules.
  • Use a Singleton pattern on your configuration instances, preferable by creating a wrapper or loader that makes sure your filesystem cache is not tested more than once in a single execution.

A somewhat refactored example is added below, because my project one was littered with project related code, in which I use constants for the config directory and environment. (Which saves you passing around the current environment, and saves you a call to the static setDirectory when you might not even be using the class, and hence autoloading too much code too early.)

/**
* Zend Config wrapper to allow for cached configurations
* as well as runtime cache loading wrapping
*
* @author Roonaan (www.roonaan.nl)
*/

class My_Project_Config {
       
    /*
     * Convenience constant to use as $type attribute in order to retrieve a Zend_Config object.
     */

    const CONFIG_AS_ZENDCONFIG = 'z';
   
    /*
     * Convenience constant to use as $type attribute in order to retrieve a configuration array.
     */

    const CONFIG_AS_ARRAY = 'a';
   
    private static $_instance = null;
    private static $_cache = null;
    private static $_directory = '';
   
    /**
    * Get a config array or Zend_Config instance for the given
    * xml file.
    *
    * @param String $file
    *   Configuration Xml file which will be prefixed with any provided directory when assigned thru setDirectory
    * @param String $type
    *   Define whether a Zend_Config instance or an array needs to be returned.
    * @param String $environment
    *  
    *
    * @return Zend_Config|Array
    */

    public static function &getInstance($file = 'config.xml', $type = self::CONFIG_AS_ZENDCONFIG, $environment = 'production') {
   
        $instanceKey = $file.'/'.$type;
       
        if(!isset(self::$_instance[$instanceKey])) {
       
            # Determine the cache key
            $key = str_replace('.','', $file);
           
            # Cache miss
            if(!is_object(self::$_cache)) {
                $zc = new Zend_Config_Xml(self::$_directory . DIRECTORY_SEPARATOR . $file, $environment, false);
                $config = array(
                    self::CONFIG_AS_ZENDCONFIG => $zc,
                    self::CONFIG_AS_ARRAY => $zc->toArray()
                );
            # Cache hit
            } else if(!($config = self::$_cache->load($key))) {
                $zc = new Zend_Config_Xml(self::$_directory . DIRECTORY_SEPARATOR . $file, $environment, false);
                $config = array(
                    self::CONFIG_AS_ZENDCONFIG => $zc,
                    self::CONFIG_AS_ARRAY => $zc->toArray()
                );
                self::$_cache->save($config, $key);
            }
           
            # Save both the Zend_Config as the config array
            self::$_instance[$file.'/'.self::CONFIG_AS_ZENDCONFIG] = $config[self::CONFIG_AS_ZENDCONFIG];
            self::$_instance[$file.'/'.self::CONFIG_AS_ARRAY]      = $config[self::CONFIG_AS_ARRAY];
        }
       
        # Return the correct cache object
        return self::$_instance[$instanceKey];
    }
   
    /**
     * Set the Zend_Cache object that is used to store parsed XML files.
     *
     * @param Zend_Cache $cache
     */

    public static function setCache(&$cache) {
        self::$_cache = $cache;
    }
   
    /**
     * Set a root directory to be used when looking up config files.
     *
     * @param String $dir Directory path
     */

    public static function setDirectory($dir) {
        if(!is_dir($dir)) {
            return;
        }
        self::$_directory = $dir;
    }
}
Be Sociable, Share!

Tags: , ,

Leave a Comment

This blog is kept spam free by WP-SpamFree.