Alex Rivera | Logout

Parsing an "advanced" INI file with PHP

Asked 2010-07-13T22:50:20.133
13

Basically, I would like a simple, easy, one-file way to parse an INI file with "advanced" features, like section inheritance and property nesting, like Zend_Config_Ini.

For example:

[foo]
a = 1
b.a = 2
b.b = 3
b.c = 4
c = 5

[bar : foo]
b.b = 17
c = 42

Would parse into

array(
  'foo'=>array(
    'a'=>'1',
    'b'=>array(
      'a'=>'2',
      'b'=>'3',
      'c'=>'4'
    ),
    'c'=>'5'
  ),
  'bar'=>array(
    'a'=>'1',
    'b'=>array(
      'a'=>'2',
      'b'=>'17',
      'c'=>'4'
    ),
    'c'=>'42'
  )
)

PHP's built-in parse_ini_file, doesn't handle anything other than simple INI's with simple sections and simple keys.

My problem with using Zend_Config_Ini is that I would have to include virtually the whole Zend_Config subpackage, and is super-bloated and configurable.

Is there a small and simple library available to parse this?
If not, is there an easy implementation I'm not seeing?

By small and simple, I mean something like the sfYaml of INI files.

To my (very inexperienced) eyes, I would have to parse through once with parse_ini_file, then come back and resolve inheritance, then run through each section and expand the keys recursively...

UPDATE: Since this seems to be a popular question, I would like to note that I have a simple class implementing this on GitHub, feel free to send pull requests, issues, etc.

Edit
Report

1 Answer

0

I've wrote something like this and for now it's working ok for me:

        $config = array();
        $configSrc = parse_ini_file( $filePath, true );
        foreach( $configSrc as $sectionName => $section )
        {
            $config[$sectionName] = array();
            foreach( $section as $itemName => $item )
            {
                $itemNameArray = explode( '.', $itemName );
                eval( sprintf('$config[$sectionName][\'%s\'] = $item;', join("']['", $itemNameArray)) );
            }
        }

        // marge inheritance;
        foreach( $config as $sectionName => $section )
        {
            $ancestryArray = explode( ':', $sectionName );
            $ancestryCount = count( $ancestryArray );
            if( $ancestryCount > 1 )
            { //
                $config[$sectionNameTrimmed = trim($ancestryArray[0])] = array();
                $ancestryArray = array_reverse( array_slice($ancestryArray, 1) );
                foreach( $ancestryArray as $ancestryName )
                {
                    $ancestryName = trim( $ancestryName );
                    if( isset($config[$ancestryName]) ) {
                        $config[$sectionNameTrimmed] = array_replace_recursive( $config[$sectionNameTrimmed], $config[$ancestryName] );
                    }
                }

                $config[$sectionNameTrimmed] = array_replace_recursive( $config[$sectionNameTrimmed], $section );
                unset( $config[$sectionName] );
            }

        }
answered 2013-06-15T07:09:02.113

Your Answer