Akrabat_Config (2nd Attempt)

Update! This version has been superceded! Check out Akrabat_Config (Take Three!) for an even better version…

Nico Edtinger was kind enough to review Akrabat_Config and pointed out that it wouldn't handle a key with multiple dots in it. His post to fw-general:

One method I don't "like" is processSection(). If I have a name like "foo.bar.baz" it would be saved as $config['foo']['bar'], dropping the last part because you explode without a third parameter. It should be
$pieces = explode('.', $key, 2);

I'd also change the check for a dot to
if(strpos($key, '.')) {

That would work with a key with a leading dot (being stored just as is instead of $config[''][...]) and the explode doesn't need to parse a string that doesn't have a dot anyway and create an array that's not needed.

Thus, this is my second attempt at Akrabat_Config:

The new tests are:

<?php
require_once 'PHPUnit2/Framework/TestCase.php';
include "Zend.php";

class ConfigTest extends PHPUnit2_Framework_TestCase
{
    protected $iniFilename;
    function setUp()
    {
        $this->iniFilename dirname(__FILE__).'/data/config.ini';
    }

    function testLoadAll()
    {
        Zend::loadClass('Akrabat_Config');
        $config = new Akrabat_Config($this->iniFilename'all');
        $this->assertEquals('all'$config->hostname);
        $this->assertEquals('all'$config->test['me']);
    }

    function testInclude()
    {
        Zend::loadClass('Akrabat_Config');
        $config = new Akrabat_Config($this->iniFilename'staging');
        $this->assertEquals('staging'$config->hostname);
        $this->assertEquals('staging'$config->test['me']);
    }

    function testMultiLevels()
    {
        Zend::loadClass('Akrabat_Config');
        $config = new Akrabat_Config($this->iniFilename'multi');
        zend::dump($config);
        $this->assertEquals('four'$config->one['two.three']);
        $this->assertEquals('five'$config->one['two.three.four']);
    }

    function testLeadingDot()
    {
        Zend::loadClass('Akrabat_Config');
        $config = new Akrabat_Config($this->iniFilename'dot');
        $this->assertEquals('dot'$config->get("."));
        $this->assertEquals('doubledot'$config->get(".."));
        $this->assertEquals('t-dot'$config->get("t."));
        $this->assertEquals('dot-t'$config->get(".t"));
    }
}

?>

with data/config.ini:

[all]
hostname = all
test.me = all

[staging]
include = all
hostname = staging
test.me = staging

[multi]
one.two.three = four
one.two.three.four = five
one.two..three = dotdotthree

[dot]
. = dot
.. = doubledot
t. = t-dot
.t = dot-t

and Akrabat_Config looks like this:

<?php

class Akrabat_Config
{
    private $_config;

    /**
     * Load the section $section from the ini file called $filename.
     * If any keys with $section are called "include", then the section
     * pointed to by the "include" is then included first. Thus, the keys
     * in $section will override any keys of the same name in the sections
     * that have been "include"ed.
     *
     * example ini file:
     *      [all]
     *      db.connection = database
     *      hostname = live
     *
     *      [staging]
     *      include = all
     *      hostname = staging
     *
     * after callgin $config = new Akrabat_Config($file, 'staging'); then
     *      $config->hostname = staging
     *      $config->db['connection'] = database
     *
     *
     * @param string $filename
     * @param string $section
     */
    function __construct($filename$section)
    {
        $iniArray parse_ini_file($filenametrue);

        $config = array();
        if(isset($iniArray[$section]))
        {
            foreach($iniArray[$section] as $key => $value)
            {
                if($key == 'include')
                {
                    if(isset($iniArray[$value]))
                    {
                        $config array_merge($config$this->processSection($iniArray[$value]));
                    }
                    unset($iniArray[$section][$key]);

                }
            }
            $config array_merge($config$this->processSection($iniArray[$section]));
        }
        else
        {
            throw new Exception("No section '$section' in $filename'");
        }
        $this->_config $config;
    }

    /**
     * Helper function to handle single level namespace in the key
     *
     * @param array $section
     * @return array
     */
    protected function processSection($section)
    {
        $config = array();
        foreach($section as $key=>$value)
        {
            if(strpos($key'.'))
            {
                $pieces explode('.'$key2);
                if(!empty($pieces[1]))
                {
                    $config[$pieces[0]][$pieces[1]] = $value;
                }
                else
                {
                    $config[$key] = $value;
                }
            }
            else
            {
                $config[$key] = $value;
            }

        }
        return $config;
    }

    /**
     * @param string $name
     * @param mixed $default
     * @return mixed
     */
    function get($name$default=false)
    {
        $result $default;
        if(isset($this->_config[$name]))
        {
            $result $this->_config[$name];
        }
        return $result;
    }

    /**
     * magic function so that $config->value will work.
     *
     * @param string $name
     * @return mixed
     */
    function __get($name)
    {
        return $this->get($name);
    }

}
?>

2 Responses to “Akrabat_Config (2nd Attempt)”

  1. 1 Thomas

    Looks interesting. I've always hated to have my settings all over the place. It's also something that I don't like in my bootstap file. It's clutter ;) Then again, there ini functions in PHP if i'm not mistaken, so this could be considered reinventing the wheel…

  2. 2 Rob...

    Yes - this class is a thin wrapper around the ini handling function. Though it provides additional functionality by allowing for overriding of keys in one section with keys in another.

    On the fw-general list we are talking about allowing for loading multiple files into one config object. I quite like that idea so might play with it tonight.

The views expressed in these comments are not the views of the publisher. However, we believe in the rights of others to express their legitimate views and concerns. Any legitimate complaint emailed to rob@akrabat.com will be seriously considered and the post reviewed as desirable and necessary.

Leave a Reply

Pre order