Zend_Config Proposal v3: Akrabat_Config (8)
After discussion with Jayson on the Zend Framework’s fw-general list and dealing with some excellent bug reports by Richard (aka OpenMacNews), I’ve come to the conclusion that the implementation of Akrabat_Config is wrong.
I’ve redone it as two separate classes with no base class. We now have:
- Akrabat_Config
- Akrabat_Config_ini
Akrabat_Config takes an associative array and provides read only access to it as properties properties . It also implements Countable and Iterator to make life easier. Akrabat_Config_ini loads an ini file and creates an associative array. Therefore Akrabat_Config_Ini only deals with all the handling of the “extends” keyword and nesting using full-stops in the key name. Akrabat_Config only deals with providing data access.
All in all much simpler!
I’ve updated the code to version 0.8(!):
Akrabat_Config_0.8.zip
I’ve also sorted out a new version of the Zend_Config proposal, which is now at version 3:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 Zend Framework Component ProposalProposed Component Name-----------------------------------------------Zend_ConfigProposers-----------------------------------------------Rob Allen (rob@akrabat.comRevision-----------------------------------------------3 - 21 May 2006: Further reworking based on mailing list.Overview-----------------------------------------------Zend_Config is a very simple configuration file reader.It provides an easy means to read configuration filesand access the data within them as a set of key->valuepairs. It will support at least one nested level of data.Initially providing support for ini files, it shouldbe easy to extend for other formats such as YAML.References-----------------------------------------------Mailing list thread resurrected here:http://www.zend.com/lists/fw-general/200604/msg00178.html.Unfortunately, I could not find the original post by Andi Gutmansin the archives.Other discussion can be found here:http://www.akrabat.com/index.php?s=Akrabat_ConfigFeedback on v1 from Zend is discussed here:http://www.zend.com/lists/fw-general/200605/msg00134.htmlPrototype code can be found here:http://www.akrabat.com/2006/05/13/zend_config-proposal-v2/Mailing list feedback on v2 is discussed here:http://www.zend.com/lists/fw-general/200605/msg00563.htmlMailing list discussion on v2.1 is here:http://www.zend.com/lists/fw-general/200605/msg00748.htmlRequirements-----------------------------------------------* Ability to load configuration information from a single config fileand provide access to the data as object properties.* A top level section name must be specified for loading.* Optional option to allow modification of the config data held inmemory.* No ability to modify the original data in the config file.* For ini files, support for "namespaces" using the syntax:namespace.property = value* Iterator is implemented for easily listing of configurationinformation.* A special "inheritence keyword "extends" will be be used to allow forincluding additional sections within this section. For ini files,the syntax would be:extends = sectionDependencies on Other Framework Components-----------------------------------------------Zend_ExceptionTheory of Operation-----------------------------------------------Zend_Config loads an provides a property based interface to an array.The data is read only unless $allowModifications is set to true onconstruction. Zend_Config also implements Countable and Interator tofacilitate easy access to the data.Sometimes it is necessary to get at a group of config variables as anarray (e.g. the $config paramter in Zend_Db::factory()). Zend_Configprovides the function "asArray()" to allow easy integration with suchrequirements.Zend_Config_Ini is a class thatloads ini files and creates andassociated array for use by Zend_Config. It loads a single section fromthe specified ini file. It supports using the full stop character (".")in a key name to provide additional nesting levels. That is, a key named"db.name" will be represented in the array as $data['db']['name'].Zend_Config_ini also supports loading of keys from one section of theini file into another section. This is done using a special key called"extends". It is possible for the parent section to itself extend fromanother section. Multiple inheritence such that a section can extendfrom two or more sections is not permitted.In order to make it easy to use with Zend_Config, Zend_Config_Ini has astatic method, "load()", which loads the ini file and returns the array.In the future, should there be demand for other config file types, otherZend_Config_XXX classes can be created for use by Zend_Config. The onlyrequirement would be for such classes to be able to generate anassociative array for loading into Zend_Config.Class Index-----------------------------------------------Zend_Config_ExceptionZend_ConfigZend_Config_IniUse Cases-----------------------------------------------Given the following "myapp.ini" file:[all]namespace.property = exampledb.connection = foodb.name = bardb.password = pwdhostname = www.zend.com[dev]extends=allhostname=andi_boxdb.name=local[andi_dev]extends=developmenthostname=andi_boxdb.connection=localhost[staging]extends=allhostname=dev.zend.comThen we can do something like:< ?php$obj=new Zend_Config(Zend_Config_Ini::load('myapp.ini', 'andi_dev'));print $obj->hostname; // prints "andi_box"print $obj->db->connection; // prints "localhost"print $obj->db->name; // prints "local"print $obj->db->password; // prints "pwd"?>Example use with Zend_Db:"db.ini" file:[all]db.type = pdoMssqldb.config.host = localhostdb.config.username = userdb.config.password = pwddb.config.dbname = db< ?php$obj=new Zend_Config(Zend_Config_Ini::load('db.ini', 'all'));$db = Zend_Db::factory($obj->db->type, $obj->db->config->asArray());?>Class Skeletons-----------------------------------------------class Zend_Config_Exception extends Zend_Exception {}class Zend_Config implements Countable, Iterator{protected $_allowModifications;protected $_iterationPointerValid;protected $_data;/*** Akrabat_Config provides a property based interface to* an array. The data is read only unless $allowModifications* is set to true on construction.** Akrabat_Config also implements Countable and Interator to* facilitate easy access to the data.** @param array $array* @param boolean $allowModifications*/public function __construct($array, $allowModifications=false) {}/*** Ensure that the key is a valid PHP property name** @param string $key* @return boolean*/protected function isValidKeyName($key) {}/*** Magic function so that $obj->value will work.** @param string $name* @return mixed*/public function __get($name) {}/*** Only allow setting of a property if $allowModifications* was set to true on construction. Otherwise, throw an exception.** @param string $name* @param mixed $value*/public function __set($name, $value) {}/*** Return an associative array of the stored data.** @return array*/public function asArray()/*** Support isset() overloading on PHP 5.1** @param string $name* @return boolean*/protected function __isset($name)/*** Defined by Countable interface*/function count() {}/*** Defined by Interator interface*/function current () {}function key () {}function next () {}function rewind () {}function valid () {}}class Zend_Config_Ini{/*** Load $section from an ini file called $filename into* an associative array.** If any keys with $section are called "extends", then the section* pointed to by the "extends" is then included into the properties.* Note that the keys in $section will override any keys of the same* name in the sections that have been included via "extends".** If any key includes a ".", then this will act as a separator to* create a sub-property.** @param string $filename* @param string $section* @return array*/public static function load($filename, $section) {}/*** Helper function to process each element in the section and handle* the "extends" inheritance keyword. Passes control to processKey()* to handle the "dot" sub-property syntax in each key.** @param array $iniArray* @param string $section* @param array $config* @return array*/protected function processExtends($iniArray, $section, $config) {}/*** Assign the key's value to the property list. Handle the "dot"* notation for sub-properties by passing control to* processLevelsInKey().** @param array $config* @param string $key* @param string $value* @return array*/function processKey($config, $key , $value) {}/*** Helper function to handle the "dot" namespace syntax in the key.* Uses "." as the separator.** @param array $parent* @param string $key* @param string $value* @return array*/protected function processLevelsInKey($parent, $key, $value) {}}