Zend_Config strategies

Tibo BeijenNovember 30th, 2008
zend_config-strategies

As applications often need to run on different setups (think: develop, test, production), configuration settings can usually be divided in a static ‘application’ part and a more dynamic ‘environment’ part. Zend Framework offers a very flexible set of classes that help reading and organizing configuration data and making it available throughout the entire application. But, as very often, there is no ‘only way’.

Loading configuration data

Basically there are three ways of loading configuration data:

  • 1.Using Zend_Config and passing a PHP array as parameter
  • 2.Using Zend_Config_Ini to load an ini configuration file
  • 3.Using Zend_Config_Xml to load an xml configuration file
$configData = array(
  'somecategory'  => array(
    'somesetting'     => 'somevalue',
  )
);
  // 1. Load array
$config = new Zend_Config($configData);
  // 2. Load ini file
$config = new Zend_Config_Ini('/path/to/config.ini');
  // 3. Load xml file
$config = new Zend_Config_Xml('/path/to/config.xml');

Alternatively, you can specify a file containing an array as require() returns the return value of a PHP script being included:

config.php

<?php
$CONFIG['somecategory']['somesetting'] = 'somevalue';
 
return $CONFIG;
  // 1b Load array
$config = new Zend_Config(require 'path/to/config.php');

Using configuration data

Zend_Config creates a hierachy of Zend_Config instances. So a specific part of the total configuration data can be extracted and passed to a specific component. All subparts behave the same. If the component requires configuration to be passed as an array the toArray() method can be used. Instead of accessing values as properties one can also use the get() method. The advantage of get() is that a default value can be supplied to be used when the requested variable isn’t available.

  // configure an instance using a specific part of the config
$modelComponent = new ModelComponent($config->components->componentName);
  // Or, if the component requires an array
$modelComponent = new ModelComponent($config->components->componentName->toArray());
  // Get an optional config setting, supplying a default value
$someValue = $config->common->get('someValue','myDefaultValue');

The data contained in Zend_Config is read-only which is normally a good thing. In case the configuration data has to be changed this can be overridden by supplying an additional parameter in the constructor. Then after making the neccessary changes the config object can be ’sealed’ by calling setReadOnly().

  // read config with $allowModifications set to true
$config = new Zend_Config(require 'path/to/config.php',true);
 
  // perhaps change some bits here and there
if ($fullMoonMadness)
{
  $config->site->theme = 'silver';
  $config->blog->allowComments = false;
}
 
  // and prevent accidental modification
$config->setReadOnly();

To make the loaded configuration available throughout the entire application, Zend_Registry is probably the tool of choice.

$config = new Zend_Config(require 'path/to/config.php');
  // and store in registry
Zend_Registry::getInstance()->set('config', $config);

Organizing configuration data

When using ini or xml configuration files, sections can be declared. On loading the file the section to be used can be specified. A section can extend other sections thereby allowing configuration data to have a certain hierarchy.

Ini-file example:

[production]
www_root = www.mysite.com
site.title = "My Website - "
 
[test : production]
www_root = test.mysite.com

The root node of XML files can be named arbitrarily. If you want to use sections the first level in the XML has to correspond to the section requested. There are two reserved attributes: value and extends. Other attributes can hold values that otherwise would be childnodes. See example that holds the same data as the Ini file above:

<?xml version="1.0"?>
<config>
  <production>
	<www_root>www.mysite.com</www_root>
    <site title="My Website - " />
  </production>
  <test extends="production">
   <www_root value="test.mysite.com" />
 </test>
</config>

Now the section-specific configuration can be loaded by specifying a second parameter in the constructor:

$config = new Zend_Config_Xml('/path/to/config.xml','test');

Ini, XML or Array?

As mentioned at the top of this article: There is no ‘only’ way and there is no ‘right’ or ‘wrong’ way. Of course there are aspects that can make you favor one approach over the other, the most notable being:

  • Only Ini and XML provide sections, allowing you to use hierarchic configuration data
  • Ini and especially XML are better suited for tooling: Software other than PHP can read or modify configuration data.
  • When using ini files it is not possible to use quotes in a value.
  • PHP arrays have the benefit that you can put program logic in them. For example, you can construct variables based on defaults that are set initially. See example below
$CONFIG['defaults']['fs_root'] = '/var/www/mysite_com/';
// ...
$CONFIG['locations']['libraries']['zf'] = $CONFIG['defaults']['fs_root'].'lib/zf/';
 
return $CONFIG;

2009-05-15: added example of loading specific section by passing section parameter to constructor

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Leave a Reply

(required)
(will not be published, required)