Oct 09
5
Load Zend_Config_XML files using a cache
Leave a comment »
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;
}
}
* 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;
}
}
Related posts: