Zend Framework: Config Any

AttachmentSize
ZExt_Config_Any.php3.65 KB

Since I was on a role with writing the ZExt Config Yml and ZExt_Config_Writer_Yaml objects, I decided to try something just a little off the beaten track. ZExt_Config_Any allows one to specify a config file of any supported type, leaving off the file extension, and having it correctly build the Zend_Config object. e.g., given the file "../application/config", this object will look in "../application/" for a xml, yml, and ini file, loading the first one it discovers using the appropriate object type.

The use case for this is narrow but (IMHO) significant. In my case, an app I'd been working on requires that several config files be provided by other hosted apps. Rather than force the developers of those apps to use a specific config file format, they are allowed to choose from any of the supported file types so long as the files have the correct name and location.

Edit 2009-04-10: I've changed the object name to "Yaml" upon realizing I wasn't following the established convention for doing so (even though it seems to ME that use of "Ini" and "Xml" might set a greater precedence for using a "Yml" extenesion).

An example call to this function might look something like this; note that I'm using "ZExt" as the library name here (as in "Zend-Extended") which is just an arbitrary name I've selected for the sake of example:

<?php
. . .
$config = new ZExt_Config_Any('../application/config.yml', 'staging');
. . .

Aaaaaand the ZExt_Config_Any class itself:

<?php
/**
 * @category   ZExt
 * @package    ZExt_Config
 * @author     Sean P. O. MacCath-Moran
 * @email      zendcode@emanaton.com
 * @website    http://www.emanaton.com
 * @copyright  This work is licenced under a Attribution Non-commercial Share Alike Creative Commons licence
 * @license    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
*/


/**
 * @see Zend_Config
*/
require_once 'Zend/Config.php';

/**
 * @uses       ZExt_Config_Any
 * @package    ZExt_Config
 * @author     Sean P. O. MacCath-Moran
 * @email      zendcode@emanaton.com
 * @website    http://www.emanaton.com
 * @copyright  This work is licenced under a Attribution Non-commercial Share Alike Creative Commons licence
 * @license    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
*/


class ZExt_Config_Any extends Zend_Config {
  /**
   * Extension types to attempt and their associated class
   *
   * @var array
  */
  protected $_extensions = array(
    'ini'=>'Zend_Config_Ini',
    'xml'=>'Zend_Config_Xml',
    'yml'=>'ZExt_Config_Yaml',
    'yaml'=>'ZExt_Config_Yaml',
  );

  /**
   * File extension discovered for the provided filename
   *
   * @var array
  */
  protected $_extensionType = '';


  /**
   * This class provides the ability to load a file based on name but irrespective of extension. Zend and ZExt Config
   * have the ability to load xml, ini, and yml files, so these are the types that are checked for. The $section and
   * $options values are passed on to the constor of the appropriate class (as determined by the file's extension).
   *
   * @param  string        $filename
   * @param  string|null   $section
   * @param  boolean|array $options
   * @throws Zend_Config_Exception
   * @return void
  */
  public function __construct($filename, $section = null, $options = false) {

    // If filename is empy, processing cannot proceed.
    if (empty($filename)) {
      /**
       * @see Zend_Config_Exception
      */
      require_once 'Zend/Config/Exception.php';
      throw new Zend_Config_Exception('Filename is not set');
    }

    $dirname = dirname($filename);

    // If directory does not exist, processing cannot proceed.
    if (!is_dir($dirname)) {
      /**
       * @see Zend_Config_Exception
      */
      require_once 'Zend/Config/Exception.php';
      throw new Zend_Config_Exception('The directory "'.$dirname.'" does not exist');
    }

    $config = false;
    foreach ($this->_extensions as $extension=>$class) {
      $file_with_ext = $filename.'.'.$extension;

      // if the filename ends in this extension, then use the filename as is, else
      // check for file with the extension appended.
      if (preg_match('/[.]'.$extension.'$/', $filename)) {
        $config = new $class($filename, $section, $options);
      } elseif (is_file($file_with_ext)) {
        $config = new $class($file_with_ext, $section, $options);
      }

      // if file was found and config created then stop searching
      if ($config !== false) {
        $this->_extensionType = $extension;
        break;
      }
    }

    // If a file was not found, then processing cannot proceed.
    if ($config === false) {
      /**
       * @see Zend_Config_Exception
      */
      require_once 'Zend/Config/Exception.php';
      throw new Zend_Config_Exception('There is no file named "'.$filename.'" with an acceptable extension (i.e. '.implode(', ', array_keys($this->_extensions)).').');
    }

    // construct this config object from the temp config object
    parent::__construct($config->toArray(), !$config->readOnly());

    // populate local protect variable from the temp config object
    $this->_extends = $config->getExtends();
    $this->_loadedSection = $config->getSectionName();
  }

}