RE: a better ini parser WAS: parse_ini_file() seems to be broken in PHP 5.2.4-2ubuntu5.12

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Since the default ini parser is pretty much useless because it doesn't
convert null/true/false values, nor convert integers/numbers, nor handle
all the ; comment styles (inline for example), nor trim extra white space,
and the list goes on and on...

I wrote a better one -- here's the first stab at it. I'm sure I'll improve
it as needed, but you're free to use as you like and hopefully it will save
someone else the pain and wasted effort on parse_ini_file():

<?php
/**
 * INI file parser
 *
 * @author		Daevid Vincent <daevid@xxxxxxxxxx>
 * @date		Created: 2010-11-09
 */

class IniParser
{
	private $file;
	public  $ini_array;

	/**
	* Constructor and acts as a singleton for the same $file
	*
	* @access 	public
	* @return 	object
	* @param	string $file the .ini file to load with full path
	* @param	boolean $process_sections (true) return a
multi-hash broken down by sections
	* @param	boolean $explode (false) split . keys into
sub-array elements
	* @author 	Daevid Vincent [daevid@xxxxxxxxxx]
	* @date    	2010-11-09
	*/
	function __construct($file, $process_sections=true, $explode=false)
	{
		if ($_SESSION['INI_PARSER'][$file])
		{
			//echo "using pre-made version<br>";
			return $_SESSION['INI_PARSER'][$file];
		}

		$this->file = $file;

		//[dv] okay so parse_ini_file() is basically a USELESS POS
		//	   not only does it NOT convert true/false/null to
proper equivalents, but it mangles the values to be "1"(strings)
		//	   verified with 5.2.4 to 5.3.3, so not much hope
for using this function natively
		//$this->ini_array =
parse_ini_file($file,$process_sections);
		$this->ini_array = $this->read_ini_file($file);
		$this->transpose_ini();

		if ($explode) $this->explode_ini();

		//TODO: handle the 'embrace extend' functionality that Zend
Framework provides with the [section : section] format

		//echo "using new version<br>";
		$_SESSION['INI_PARSER'][$file] = $this;
		return $this;
	}

	private function read_ini_file($file)
	{
	    $handle = @fopen($file, "r");
	    if (!$handle) throw new Exception('Cannot open INI file
'.$file);
	    $contents = @fread($handle, filesize($file));
	    if (!$contents) throw new Exception('Cannot read INI file
'.$file);

	    $section = '';
	    $contents = split("\n", trim($contents));
	    foreach ($contents as $k => $line)
	    {
	    	$line = trim($line);
	    	if (!$line) continue;
	        if (in_array($line[0], array(';','#'))) continue;

	        if ($line[0] == "[")
            {
                preg_match('/\[(.*)\]/', $line, $pmatches);
                $section = $pmatches[1];
            }
            else
            {
                $keyval = explode('=', $line);
                $tmp = explode(';',$keyval[1]);
                $mykey = trim($keyval[0]);
                $myval = trim($tmp[0]);

                if (substr($mykey, -2) == '[]')  //check for arrays
                	$ini_file[$section][substr($mykey, 0, -2)][] =
$myval;
                else
                	$ini_file[$section][$mykey] = $myval;
            }
	    }

	    @fclose($handle);
	    return $ini_file;
	}

	private function transpose_ini()
	{
		foreach($this->ini_array as $heading => &$key_vals)
		{
			foreach ($key_vals as $k => &$v)
			{
				//echo "$k => $v<br>\n";
				if (is_numeric($v))
				{
					$i = intval($v);
					if ($i == $v) $v = $i;
				}
				else
				switch (strtolower($v))
				{
					case 'true':  $v = true; break;
					case 'false': $v = false; break;
					case 'null':  $v = null; break;
				}
			}
		}
	}

	/*
	 * not used currently, but took a while to get this working so keep
for future reference/use
	public function explode_ini()
	{
		$ini_array = array();

		foreach($this->ini_array as $heading => $key_vals)
		{
			foreach ($key_vals as $k => $v)
			{
				$path = 'ini_array[\''.$heading.'\']';
				$subsection = explode('.', $k);
				foreach ($subsection as $ss) $path .=
'[\''.$ss.'\']';
				if (is_string($v)) $path = '$'.$path.' =
\''.$v.'\';'; else	$path = '$'.$path.' = '.$v.';';
				eval($path); //it's not elegant but it
works!
			}
		}

		$this->ini_array = $ini_array;
	}
	*/

	public function get_value($section, $key)
	{
		//echo "$section / $key =
".$this->ini_array[$section][$key]."<br>\n";
		if (is_string($key))
		{
			return $this->ini_array[$section][$key];
		}

		//TODO: else it's an (exploded) nested array so traverse to
find the value
	}

	public function __toString()
	{
		var_dump($this->ini_array);
		return '';
	}
}
?>



$mypath = dirname(__FILE__);
require_once $mypath.'/classes/IniParser.class.php';
try
{
	$config_ini = new IniParser($mypath.'/config.ini', true);
}
catch (Exception $e)
{
	exit('Caught Exception parsing ini
file.<br>'.$e->getMessage()."\n");
}
if (!is_array($config_ini->ini_array)) exit('No config.ini loaded. Can not
proceed.');



$myinioption = $config_ini->get_value('some_section',
'some.ini.config.option.here');


-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux