PHP
downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

parse_ini_string> <move_uploaded_file
Last updated: Tue, 30 Jun 2009

view this page in

parse_ini_file

(PHP 4, PHP 5)

parse_ini_fileParse a configuration file

Description

array parse_ini_file ( string $filename [, bool $process_sections= false [, int $scanner_mode= INI_SCANNER_NORMAL ]] )

parse_ini_file() loads in the ini file specified in filename , and returns the settings in it in an associative array.

The structure of the ini file is the same as the php.ini's.

Parameters

filename

The filename of the ini file being parsed.

process_sections

By setting the process_sections parameter to TRUE, you get a multidimensional array, with the section names and settings included. The default for process_sections is FALSE

scanner_mode

Can either be INI_SCANNER_NORMAL (default) or INI_SCANNER_RAW. If INI_SCANNER_RAW is supplied, then option values will not be parsed.

Return Values

The settings are returned as an associative array on success, and FALSE on failure.

Changelog

Version Description
5.3.0 Added optional scanner_mode parameter.
5.2.7 On syntax error this function will return FALSE rather then an empty array.
5.2.4 Keys and section names consisting of numbers are now evaluated as PHP integers thus numbers starting by 0 are evaluated as octals and numbers starting by 0x are evaluated as hexadecimals.
5.0.0 Values enclosed in double quotes can contain new lines.
4.2.1 This function is now affected by safe mode and open_basedir.

Examples

Example #1 Contents of sample.ini

; This is a sample configuration file
; Comments start with ';', as in php.ini

[first_section]
one = 1
five = 5
animal = BIRD

[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"

[third_section]
phpversion[] = "5.0"
phpversion[] = "5.1"
phpversion[] = "5.2"
phpversion[] = "5.3"

Example #2 parse_ini_file() example

Constants may also be parsed in the ini file so if you define a constant as an ini value before running parse_ini_file(), it will be integrated into the results. Only ini values are evaluated. For example:

<?php

define
('BIRD''Dodo bird');

// Parse without sections
$ini_array parse_ini_file("sample.ini");
print_r($ini_array);

// Parse with sections
$ini_array parse_ini_file("sample.ini"true);
print_r($ini_array);

?>

The above example will output something similar to:

Array
(
    [one] => 1
    [five] => 5
    [animal] => Dodo bird
    [path] => /usr/local/bin
    [URL] => http://www.example.com/~username
    [phpversion] => Array
        (
            [0] => 5.0
            [1] => 5.1
            [2] => 5.2
            [3] => 5.3
        )

)
Array
(
    [first_section] => Array
        (
            [one] => 1
            [five] => 5
            [animal] => Dodo bird
        )

    [second_section] => Array
        (
            [path] => /usr/local/bin
            [URL] => http://www.example.com/~username
        )

    [third_section] => Array
        (
            [phpversion] => Array
                (
                    [0] => 5.0
                    [1] => 5.1
                    [2] => 5.2
                    [3] => 5.3
                )

        )

)

Example #3 parse_ini_file() parsing a php.ini file

<?php
// A simple function used for comparing the results below
function yesno($expression)
{
    return(
$expression 'Yes' 'No');
}

// Get the path to php.ini using the php_ini_loaded_file() 
// function available as of PHP 5.2.4
$ini_path php_ini_loaded_file();

// Parse php.ini
$ini parse_ini_file($ini_path);

// Print and compare the values, note that using get_cfg_var()
// will give the same results for parsed and loaded here
echo '(parsed) magic_quotes_gpc = ' yesno($ini['magic_quotes_gpc']) . PHP_EOL;
echo 
'(loaded) magic_quotes_gpc = ' yesno(get_cfg_var('magic_quotes_gpc')) . PHP_EOL;
?>

The above example will output something similar to:

(parsed) magic_quotes_gpc = Yes
(loaded) magic_quotes_gpc = Yes

Notes

Note: This function has nothing to do with the php.ini file. It is already processed by the time you run your script. This function can be used to read in your own application's configuration files.

Note: If a value in the ini file contains any non-alphanumeric characters it needs to be enclosed in double-quotes (").

Note: There are reserved words which must not be used as keys for ini files. These include: null, yes, no, true, false, on, off, none. Values null, no and false results in "", yes and true results in "1". Characters {}|&~![()^" must not be used anywhere in the key and have a special meaning in the value.

See Also



parse_ini_string> <move_uploaded_file
Last updated: Tue, 30 Jun 2009
 
add a note add a note User Contributed Notes
parse_ini_file
joe at u13 dot net
20-Jun-2009 07:46
I'm not sure why, but for some reason php's ini functions always leave out entries for me.

To solve this problem, I wrote my own ini parsing function, intended to be a replacement for parse_ini_file('file.ini', true);

<?php

function new_parse_ini($f)
{

   
// if cannot open file, return false
   
if (!is_file($f))
        return
false;

   
$ini = file($f);

   
// to hold the categories, and within them the entries
   
$cats = array();

    foreach (
$ini as $i) {
        if (@
preg_match('/\[(.+)\]/', $i, $matches)) {
           
$last = $matches[1];
        } elseif (@
preg_match('/(.+)=(.+)/', $i, $matches)) {
           
$cats[$last][$matches[1]] = $matches[2];
        }
    }

    return
$cats;

}

?>

The usage follows the Example #2 on http://us3.php.net/manual/en/function.parse-ini-file.php , except without the second parameter being 'true'.
DDRKhat
19-Jun-2009 09:11
Here is an adaption of Jomel's write_ini_file function to support arrays and eliminate redundant speechmarking on NULL values

<?php
if (!function_exists('write_ini_file')) {
    function
write_ini_file($assoc_arr, $path, $has_sections=FALSE) {
       
$content = "";

        if (
$has_sections) {
            foreach (
$assoc_arr as $key=>$elem) {
               
$content .= "[".$key."]\n";
                foreach (
$elem as $key2=>$elem2)
                {
                    if(
is_array($elem2))
                    {
                        for(
$i=0;$i<count($elem2);$i++)
                        {
                           
$content .= $key2."[] = \"".$elem2[$i]."\"\n";
                        }
                    }
                    else if(
$elem2=="") $content .= $key2." = \n";
                    else
$content .= $key2." = \"".$elem2."\"\n";
                }
            }
        }
        else {
            foreach (
$assoc_arr as $key=>$elem) {
                if(
is_array($elem))
                {
                    for(
$i=0;$i<count($elem);$i++)
                    {
                       
$content .= $key2."[] = \"".$elem[$i]."\"\n";
                    }
                }
                else if(
$elem=="") $content .= $key2." = \n";
                else
$content .= $key2." = \"".$elem."\"\n";
            }
        }

        if (!
$handle = fopen($path, 'w')) {
            return
false;
        }
        if (!
fwrite($handle, $content)) {
            return
false;
        }
       
fclose($handle);
        return
true;
    }
}
?>
jeremygiberson at gmail dot com
30-Apr-2009 11:01
Here is a quick parse_ini_file wrapper to add extend support to save typing and redundancy.
<?php
   
/**
     * Parses INI file adding extends functionality via ":base" postfix on namespace.
     *
     * @param string $filename
     * @return array
     */
   
function parse_ini_file_extended($filename) {
       
$p_ini = parse_ini_file($filename, true);
       
$config = array();
        foreach(
$p_ini as $namespace => $properties){
            list(
$name, $extends) = explode(':', $namespace);
           
$name = trim($name);
           
$extends = trim($extends);
           
// create namespace if necessary
           
if(!isset($config[$name])) $config[$name] = array();
           
// inherit base namespace
           
if(isset($p_ini[$extends])){
                foreach(
$p_ini[$extends] as $prop => $val)
                   
$config[$name][$prop] = $val;
            }
           
// overwrite / set current namespace values
           
foreach($properties as $prop => $val)
           
$config[$name][$prop] = $val;
        }
        return
$config;
    }
?>

Treats this ini:
<?php
/*
[base]
host=localhost
user=testuser
pass=testpass
database=default

[users:base]
database=users

[archive : base]
database=archive
*/
?>
As if it were like this:
<?php
/*
[base]
host=localhost
user=testuser
pass=testpass
database=default

[users:base]
host=localhost
user=testuser
pass=testpass
database=users

[archive : base]
host=localhost
user=testuser
pass=testpass
database=archive
*/
?>
prikkeldraad at gmail dot com
26-Mar-2009 02:15
When PHP dies without any warning or message when parsing the ini-file, check the values of the file. All non alphanumeric values need to be quoted.
php at e-pla dot net
29-Jan-2009 10:12
Just needed a loose and multiline function to parse ini files.

So here is my attempt:

- process multiline values
- accepts non alphanum characters (spaces, dot, equals etc...) inside keys or values
- "raw" mode
- "section" mode
- proper comment parsing
- compact coding: only 400 bytes !...

Code is here:
http://mach13.com/loose-and-multiline-parse_ini_file-function-in-php
pBakhuis at googles mail dot com (gmail)
12-Dec-2008 04:42
To those who were like me looking if this could be used to create an array out of commandline output I offer you the function below (I used it to parse mplayer output).

If you want it behave exactly the same as parse_ini_file you'll obviously have to add some code to feed the different sections to this one. Hope it's of help to someone!

<?php
/**
 * The return is very similar to that of parse_ini_file, but this works off files
 *
 * Below is an example of what it does, where the first
 * value is what you'd normally want to do, and the second and third things that might
 * happen and in case it does it's good to know what is going on.
 *
 * $anArray = array( 'default=theValue', 'setting=', 'something=value=value' );
 * explodeExplode( '=', $anArray );
 *
 * the return will be
 * array( 'default' => 'theValue', 'setting' => '', 'something' => 'value=value' );
 *
 * So the oddities here are, text after the second $string occurence dissapearing
 * and empty values resulting in an empty string.
 *
 * @return $returnArray array array( 'setting' => 'value' )
 * @param $string Object
 * @param $array Object
 */
function explodeExplode( $string, $array )
{
   
$returnArray = array();
   
    foreach(
$array as $arrayValue )
    {
       
$tmpArray = explode( $string, $arrayValue );
       
        if(
count( $tmpArray ) == 1 )
        {
           
$returnArray[$tmpArray[0]] = '';
        }
        else if(
count( $tmpArray ) == 2 )
        {
           
$returnArray[$tmpArray[0]] = $tmpArray[1];
        }
        else if(
count( $tmpArray ) > 2 )
        {
           
$implodeBack = array();
           
$firstLoop      = true;
            foreach(
$tmpArray as $tmpValue )
            {
                if(
$firstLoop )
                {
                   
$firstLoop = false;
                }
                else
                {
                   
$implodeBack[] = $tmpValue;
                }
            }
           
print_r( $implodeBack );
           
$returnArray[$tmpArray[0]] = implode( '=', $implodeBack );
        }
    }
   
    return
$returnArray;
}
?>
bas at muer dot nl
31-Oct-2008 11:52
In response to juampii_4 at hotmail dot com (10-Jul-2008 05:24):

You're parsing the ini file every time someone requests a variable. You'd have a better performing class if you were to parse it once, then store the resulting array. Requests for a value from the ini should be taken from that stored array, not by reparsing the ini over and over.
Bill Brown - macnimble.com
17-Oct-2008 02:47
Working on a project for a client recently, I needed a way to set a default configuration INI file, but also wanted to allow the client to override the settings through the use of a custom INI file.

I thought array_merge or array_merge_recursive would do the trick for me, but it fails to override settings in the way that I wanted. I wrote my own function to do what I wanted. It's nothing spectacular, but thought I'd post it here in case it saved someone else some time.

<?php
function ini_merge ($config_ini, $custom_ini) {
  foreach (
$custom_ini AS $k => $v):
    if (
is_array($v)):
     
$config_ini[$k] = ini_merge($config_ini[$k], $custom_ini[$k]);
    else:
     
$config_ini[$k] = $v;
    endif;
  endforeach;
  return
$config_ini;
};
$CONFIG_INI = parse_ini_file('../config.ini', TRUE);
$CUSTOM_INI = parse_ini_file('ini/custom.ini', TRUE);
$INI = ini_merge($CONFIG_INI, $CUSTOM_INI);
?>

This allowed me to put the default INI file above the web root with information that requires extra security (database connection info, etc.) and a writable INI file within the structure of the site without affecting the default settings of the default config.ini file.

Anyway, hope it helps.
david dot dyess at gmail dot com
04-Aug-2008 07:12
Here is another way to group values in the ini:

my.ini:

[singles]
test = a test
test2 = another test
test3 = this is a test too

[multiples]
tests[] = a test
tests[] = another test
tests[] = this is a test too

my.php:

$init = parse_ini_file('my.ini');

The same as:

$init['test'] = 'a test';
$init['test2'] = 'another test';
$init['test3'] = 'this is a test too';
$init['tests'][0] = 'a test';
$init['tests'][1] = 'another test';
$init['tests'][2] = 'this is a test too';

This works with the bool set to true also, can be useful with loops. Works with the bool set to true as well.
another_user at example dot com
24-Jul-2008 11:43
yarco dot w at gmail dot com:  Constants can be concatenated with strings, but the string segments must be enclosed in quotes.  Note to users, no joining symbol is used:

+++
; Start config.ini file here

output = "bla bla bla "TEST_TXT" bla bla bla"

; end
+++

<?php

define
("TEST_TXT","something something");
$the_array = parse_ini_file("/www/includes/config.ini");
echo
$the_array["output"];

?>

outputs...
bla bla bla something something bla bla bla
juampii_4 at hotmail dot com
10-Jul-2008 03:24
class.parseini.php
<?php
##By juan pablo tosso
class Parser
{

    public function
printini($file, $sector, $var)
    {
       
$file=$file.".ini";
       
$is=array();
       
$is= parse_ini_file($file, true);
       
trim($is);
        if(
is_array($is) && file_exists($file))
        {
            return
$is[$sector][$var];
        }else{
            return
"error";
        }
       
    }
   
   
}

?>

Ini.ini:
[test]
foo=bar

[test2]
foo1=bar1
foo2=bar2
foo bar=something else

just in another file write:

include("class.parseini.php");
$new= new Parser();
echo $new->printini("ini", "test2", "foo1");
tim {at} tim {hyphen} ryan {dot} com
02-Jul-2008 07:14
I whipped up an alternate, small (4kb) INI reader/writer class, implementing most of the features below:

 - [] array support
 - dot (.) notation heirarchies
 - sections (and non-section mode)
 - proper comment (;) parsing
 - parsing literal values (booleans, numbers, constants)
 - file reading/writing

Check it out here: http://tim-ryan.com/labs/parseINI/
asohn ~at~ aircanopy ~dot~ net
30-Apr-2008 10:27
Comments don't have to have an entire line dedicated to them. You can put a comment on the same line as a section or variable/value declaration and the built-in parse_ini_file() function will omit them. This being the case I took the liberty of revising goulven.ch AT gmail DOT com 's parse_ini() function. I also added the $process_sections argument to better reflect PHP's built-in parse_ini_file(). As soon as a semicolon is found in a line everything from that position to the end of the line is omitted so as to not become part of the value. However, any semicolon found that occurs between a single-quote or double-quote will be left alone to become part of the value.

<?php
function _parse_ini_file($file, $process_sections = false) {
 
$process_sections = ($process_sections !== true) ? false : true;

 
$ini = file($file);
  if (
count($ini) == 0) {return array();}

 
$sections = array();
 
$values = array();
 
$result = array();
 
$globals = array();
 
$i = 0;
  foreach (
$ini as $line) {
   
$line = trim($line);
   
$line = str_replace("\t", " ", $line);

   
// Comments
   
if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}

   
// Sections
   
if ($line{0} == '[') {
     
$tmp = explode(']', $line);
     
$sections[] = trim(substr($tmp[0], 1));
     
$i++;
      continue;
    }

   
// Key-value pair
   
list($key, $value) = explode('=', $line, 2);
   
$key = trim($key);
   
$value = trim($value);
    if (
strstr($value, ";")) {
     
$tmp = explode(';', $value);
      if (
count($tmp) == 2) {
        if (((
$value{0} != '"') && ($value{0} != "'")) ||
           
preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
           
preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
         
$value = $tmp[0];
        }
      } else {
        if (
$value{0} == '"') {
         
$value = preg_replace('/^"(.*)".*/', '$1', $value);
        } elseif (
$value{0} == "'") {
         
$value = preg_replace("/^'(.*)'.*/", '$1', $value);
        } else {
         
$value = $tmp[0];
        }
      }
    }
   
$value = trim($value);
   
$value = trim($value, "'\"");

    if (
$i == 0) {
      if (
substr($line, -1, 2) == '[]') {
       
$globals[$key][] = $value;
      } else {
       
$globals[$key] = $value;
      }
    } else {
      if (
substr($line, -1, 2) == '[]') {
       
$values[$i-1][$key][] = $value;
      } else {
       
$values[$i-1][$key] = $value;
      }
    }
  }

  for(
$j = 0; $j < $i; $j++) {
    if (
$process_sections === true) {
     
$result[$sections[$j]] = $values[$j];
    } else {
     
$result[] = $values[$j];
    }
  }

  return
$result + $globals;
}
?>

usage regarding semicolons:
<?php
;sample.ini

variable1  
= v1;v1
variable 2 
= "v2;v2"
variable_3  = "v3;v3;v3"
variable4   = "v4;v4" ;v4
variable 5 
= "v5;v5;v5" ;v5
variable_6 
= "v6;v6" ;v6;;
variable7   = "v7;;v7"
variable 8  = 'v8;v8'
variable_9  = 'v9;v9;v9'
variable10  = 'v10;v10' ;v10
variable 11
= 'v11;v11;v11' ;v11
variable_12
= 'v12;v12' ;v2;;
variable13  = 'v13;;v13'
variable 14 = "v14
variable_15 = 'v15
variable16  = "
v16;v16
variable 17
= v17;v17
?>
<?php
//example.php
print_r(_parse_ini_file("sample.ini"));
?>
<?php
//example.php output
Array
(
    [
variable1] => v1
   
[variable 2] => v2;v2
   
[variable_3] => v3;v3;v3
   
[variable4] => v4;v4
   
[variable 5] => v5;v5;v5
   
[variable_6] => v6;v6
   
[variable7] => v7;;v7
   
[variable 8] => v8;v8
   
[variable_9] => v9;v9;v9
   
[variable10] => v10;v10
   
[variable 11] => v11;v11;v11
   
[variable_12] => v12;v12
   
[variable13] => v13;;v13
   
[variable 14] => v14
   
[variable_15] => v15
   
[variable16] => v16
   
[variable 17] => v17
)
?>
goulven.ch AT gmail DOT com
29-Oct-2007 02:33
Warning: parse_ini_files cannot cope with values containing the equal sign (=).

The following function supports sections, comments, arrays, and key-value pairs outside of any section.
Beware that similar keys will overwrite one another (unless in different sections).

<?php
function parse_ini ( $filepath ) {
   
$ini = file( $filepath );
    if (
count( $ini ) == 0 ) { return array(); }
   
$sections = array();
   
$values = array();
   
$globals = array();
   
$i = 0;
    foreach(
$ini as $line ){
       
$line = trim( $line );
       
// Comments
       
if ( $line == '' || $line{0} == ';' ) { continue; }
       
// Sections
       
if ( $line{0} == '[' ) {
           
$sections[] = substr( $line, 1, -1 );
           
$i++;
            continue;
        }
       
// Key-value pair
       
list( $key, $value ) = explode( '=', $line, 2 );
       
$key = trim( $key );
       
$value = trim( $value );
        if (
$i == 0 ) {
           
// Array values
           
if ( substr( $line, -1, 2 ) == '[]' ) {
               
$globals[ $key ][] = $value;
            } else {
               
$globals[ $key ] = $value;
            }
        } else {
           
// Array values
           
if ( substr( $line, -1, 2 ) == '[]' ) {
               
$values[ $i - 1 ][ $key ][] = $value;
            } else {
               
$values[ $i - 1 ][ $key ] = $value;
            }
        }
    }
    for(
$j=0; $j<$i; $j++ ) {
       
$result[ $sections[ $j ] ] = $values[ $j ];
    }
    return
$result + $globals;
}
?>

Example usage:
<?php
$stores
= parse_ini('stores.ini');
print_r( $stores );
?>

An example ini file:
<?php
/*
;Commented line start with ';'
global_value1 = a string value
global_value1 = another string value

; empty lines are discarded
[Section1]
key = value
; whitespace around keys and values is discarded too
otherkey=other value
otherkey=yet another value
; this key-value pair will overwrite the former.
*/
?>
www.onphp5.com
24-Oct-2007 08:26
Looks like in PHP 5.3.0 special characters like \n are extrapolated into real newlines. Gotta use \\n.
arnapou
03-Oct-2007 01:51
I didn't find a simple ini class so I wrote that class to read and write ini files.
I hope it could help you.

Read file : $ini = INI::read('myfile.ini');
Write file : INI::write('myfile.ini', $ini);

Features :
- support [] syntax for arrays
- support . in keys like bar.foo.something = value
- true and false string are automatically converted in booleans
- integers strings are automatically converted in integers
- keys are sorted when writing
- constants are replaced but they should be written in the ini file between braces : {MYCONSTANT}

<?php

class INI {
   
/**
     *  WRITE
     */
   
static function write($filename, $ini) {
       
$string = '';
        foreach(
array_keys($ini) as $key) {
           
$string .= '['.$key."]\n";
           
$string .= INI::write_get_string($ini[$key], '')."\n";
        }
       
file_put_contents($filename, $string);
    }
   
/**
     *  write get string
     */
   
static function write_get_string(& $ini, $prefix) {
       
$string = '';
       
ksort($ini);
        foreach(
$ini as $key => $val) {
            if (
is_array($val)) {
               
$string .= INI::write_get_string($ini[$key], $prefix.$key.'.');
            } else {
               
$string .= $prefix.$key.' = '.str_replace("\n", "\\\n", INI::set_value($val))."\n";
            }
        }
        return
$string;
    }
   
/**
     *  manage keys
     */
   
static function set_value($val) {
        if (
$val === true) { return 'true'; }
        else if (
$val === false) { return 'false'; }
        return
$val;
    }
   
/**
     *  READ
     */
   
static function read($filename) {
       
$ini = array();
       
$lines = file($filename);
       
$section = 'default';
       
$multi = '';
        foreach(
$lines as $line) {
            if (
substr($line, 0, 1) !== ';') {
               
$line = str_replace("\r", "", str_replace("\n", "", $line));
                if (
preg_match('/^\[(.*)\]/', $line, $m)) {
                   
$section = $m[1];
                } else if (
$multi === '' && preg_match('/^([a-z0-9_.\[\]-]+)\s*=\s*(.*)$/i', $line, $m)) {
                   
$key = $m[1];
                   
$val = $m[2];
                    if (
substr($val, -1) !== "\\") {
                       
$val = trim($val);
                       
INI::manage_keys($ini[$section], $key, $val);
                       
$multi = '';
                    } else {
                       
$multi = substr($val, 0, -1)."\n";
                    }
                } else if (
$multi !== '') {
                    if (
substr($line, -1) === "\\") {
                       
$multi .= substr($line, 0, -1)."\n";
                    } else {
                       
INI::manage_keys($ini[$section], $key, $multi.$line);
                       
$multi = '';
                    }
                }
            }
        }
       
       
$buf = get_defined_constants(true);
       
$consts = array();
        foreach(
$buf['user'] as $key => $val) {
           
$consts['{'.$key.'}'] = $val;
        }
       
array_walk_recursive($ini, array('INI', 'replace_consts'), $consts);
        return
$ini;
    }
   
/**
     *  manage keys
     */
   
static function get_value($val) {
        if (
preg_match('/^-?[0-9]$/i', $val)) { return intval($val); }
        else if (
strtolower($val) === 'true') { return true; }
        else if (
strtolower($val) === 'false') { return false; }
        else if (
preg_match('/^"(.*)"$/i', $val, $m)) { return $m[1]; }
        else if (
preg_match('/^\'(.*)\'$/i', $val, $m)) { return $m[1]; }
        return
$val;
    }
   
/**
     *  manage keys
     */
   
static function get_key($val) {
        if (
preg_match('/^[0-9]$/i', $val)) { return intval($val); }
        return
$val;
    }
   
/**
     *  manage keys
     */
   
static function manage_keys(& $ini, $key, $val) {
        if (
preg_match('/^([a-z0-9_-]+)\.(.*)$/i', $key, $m)) {
           
INI::manage_keys($ini[$m[1]], $m[2], $val);
        } else if (
preg_match('/^([a-z0-9_-]+)\[(.*)\]$/i', $key, $m)) {
            if (
$m[2] !== '') {
               
$ini[$m[1]][INI::get_key($m[2])] = INI::get_value($val);
            } else {
               
$ini[$m[1]][] = INI::get_value($val);
            }
        } else {
           
$ini[INI::get_key($key)] = INI::get_value($val);
        }
    }
   
/**
     *  replace utility
     */
   
static function replace_consts(& $item, $key, $consts) {
        if (
is_string($item)) {
           
$item = strtr($item, $consts);
        }
    }
}

?>
thuylnt
26-Sep-2007 09:09
I need to read a ini file, modify some values in some sections, and save it. But the important thing is, i want to keep all the comments, the new lines in the right order. So i modified function parse_ini_file_quotes_safe and write_ini_file.
I think they work fine.

    function read_ini_file($f, &$r)
    {
        $null = "";
        $r=$null;
        $first_char = "";
        $sec=$null;
        $comment_chars=";#";
        $num_comments = "0";
        $num_newline = "0";

        //Read to end of file with the newlines still attached into $f
        $f = @file($f);
        if ($f === false) {
            return -2;
        }
        // Process all lines from 0 to count($f)
        for ($i=0; $i<@count($f); $i++)
        {
            $w=@trim($f[$i]);
            $first_char = @substr($w,0,1);
            if ($w)
            {
                if ((@substr($w,0,1)=="[") and (@substr($w,-1,1))=="]") {
                    $sec=@substr($w,1,@strlen($w)-2);
                    $num_comments = 0;
                    $num_newline = 0;
                }
                else if ((stristr($comment_chars, $first_char) == true)) {
                    $r[$sec]["Comment_".$num_comments]=$w;
                    $num_comments = $num_comments +1;
                }               
                else {
                    // Look for the = char to allow us to split the section into key and value
                    $w=@explode("=",$w);
                    $k=@trim($w[0]);
                    unset($w[0]);
                    $v=@trim(@implode("=",$w));
                    // look for the new lines
                    if ((@substr($v,0,1)=="\"") and (@substr($v,-1,1)=="\"")) {
                        $v=@substr($v,1,@strlen($v)-2);
                    }
                   
                    $r[$sec][$k]=$v;
                   
                }
            }
            else {
                $r[$sec]["Newline_".$num_newline]=$w;
                $num_newline = $num_newline +1;
            }
        }
        return 1;
    }

    function write_ini_file($path, $assoc_arr) {
        $content = "";

        foreach ($assoc_arr as $key=>$elem) {
            if (is_array($elem)) {
                if ($key != '') {
                    $content .= "[".$key."]\r\n";                   
                }
               
                foreach ($elem as $key2=>$elem2) {
                    if ($this->beginsWith($key2,'Comment_') == 1 && $this->beginsWith($elem2,';')) {
                        $content .= $elem2."\r\n";
                    }
                    else if ($this->beginsWith($key2,'Newline_') == 1 && ($elem2 == '')) {
                        $content .= $elem2."\r\n";
                    }
                    else {
                        $content .= $key2." = ".$elem2."\r\n";
                    }
                }
            }
            else {
                $content .= $key." = ".$elem."\r\n";
            }
        }

        if (!$handle = fopen($path, 'w')) {
            return -2;
        }
        if (!fwrite($handle, $content)) {
            return -2;
        }
        fclose($handle);
        return 1;
    }

    function beginsWith( $str, $sub ) {
        return ( substr( $str, 0, strlen( $sub ) ) === $sub );
    }
yarco dot w at gmail dot com
29-Jun-2007 08:46
parse_ini_file can't deal with const which cancate a string. For example, if test.ini file is

classPath = ROOT/lib

If you:
<?php
define
('ROOT', dirname(__FILE__));

$buf = parse_ini_file('test.ini');
?>

const ROOT would't be parsed.

But my version could work find.

<?php
// array parse_ini_file ( string $filename [, bool $process_sections] )
function parse_ini($filename, $process_sections = false)
{
  function
replace_process(& $item, $key, $consts)
  {
   
$item = str_replace(array_keys($consts), array_values($consts), $item);
  }

 
$buf = get_defined_constants(true); // PHP version > 5.0
 
$consts = $buf['user'];
 
$ini = parse_ini_file($filename, $process_sections);

 
array_walk_recursive($ini, 'replace_process', $consts);
  return
$ini;
}

define('ROOT', '/test');
print_r(parse_ini(dirname(__FILE__).'/test.ini'));

?>
Adam
25-Jun-2007 05:45
Arrays can be defined in the ini file by adding '[]' at the end of a key name. For example:

value1 = 17
value2 = 13

value3[] = a
value3[] = b
value3[] = c

Will return:
Array
(
    [value1] => 17
    [value2] => 13
    [value3] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )
)
Mildred
25-May-2007 07:42
I wrote few functions to work with ini files.

The function make_ini_file($array, &$errors)
The function read_ini($file)
The function prepare_ini($array, $maxdepth=NULL)

The function prepare_ini($array, $maxdepth=NULL)
This function will take an array as returned by the function read_ini() and will return an array as needed by the function make_ini_file() so that you can write extanded ini files easily.
If maxdepth is not given (or if maxdepth is NULL), this function will try to create sections so the keys in the sections do not have dots. if maxdepth is given, it will create sections with $maxdepth members in them (or less if it is not possible). It won't use the