parse_ini_file

(PHP 4, PHP 5, PHP 7, PHP 8)

parse_ini_fileAnalyse un fichier de configuration

Description

parse_ini_file(string $filename, bool $process_sections = false, int $scanner_mode = INI_SCANNER_NORMAL): array|false

parse_ini_file() charge le fichier filename et retourne les configurations qui s'y trouvent sous forme d'un tableau associatif.

La structure des fichiers de configuration lus est similaire à celle de php.ini.

Liste de paramètres

filename

Le nom du fichier de configuration à analyser. Si un chemin relatif est utilisé, il est évalué relatif au dossier courrant actuel, puis selon le include_path.

process_sections

En passant le paramètre process_sections à true, vous obtiendrez un tableau multidimensionnel avec les noms des sections. La valeur par défaut de ce paramètre est false

scanner_mode

Peut être INI_SCANNER_NORMAL (défaut) ou INI_SCANNER_RAW. Si INI_SCANNER_RAW est fourni, alors les valeurs en option ne seront pas analysées.

À parti de PHP 5.6.1 peut aussi être spécifié comme INI_SCANNER_TYPED. Dans ce mode les booléens, null et entiers sont préservés tant que possible. Les chaines de caractères "true", "on" et "yes" sont converties vers true. "false", "off", "no" et "none" sont considérés comme false. "null" est converti en null dans ce mode. De plus toutes les chaines de caractères numériques sont converties en entier si possible.

Valeurs de retour

La configuration est retournée sous la forme d'un tableau associatif en cas de succès, et false si une erreur survient.

Exemples

Exemple #1 Contenu du fichier sample.ini

; Ceci est un fichier de configuration
; Les commentaires commencent par ';', comme dans 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"

urls[svn] = "http://svn.php.net"
urls[git] = "http://git.php.net"

Exemple #2 Exemple avec parse_ini_file()

Les constantes (mais pas les "constantes magiques" tel que __FILE__) peuvent aussi être utilisées dans le fichier .ini, ce qui fait que si vous définissez une constante avant d'exécuter parse_ini_file(), elle sera intégrée dans les résultats. Seules les valeurs de configuration sont évaluées, et la valeur doit juste être la constante. Par exemple :

<?php

define
('BIRD', 'Dodo bird');

// Analyse sans sections
$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);

// Analyse avec sections
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);

?>

Résultat de l'exemple ci-dessus est similaire à :

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
        )

    [urls] => Array
        (
            [svn] => http://svn.php.net
            [git] => http://git.php.net
        )

)
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
                )
            [urls] => Array
                (
                    [svn] => http://svn.php.net
                    [git] => http://git.php.net
                )

)

Exemple #3 parse_ini_file() pour analyser un fichier php.ini

<?php
// Une fonction simple pour comparer les résultats ci-dessous
function yesno($expression)
{
return(
$expression ? 'Yes' : 'No');
}

// Lit le chemin du php.ini en utilisant php_ini_loaded_file()
$ini_path = php_ini_loaded_file();

// Analyse de php.ini
$ini = parse_ini_file($ini_path);

// Affichage et comparatif des valeurs. Notez que get_cfg_var()
// va donner les mêmes résultats entre les résultats analysés et chargés
echo '(analysé) magic_quotes_gpc = ' . yesno($ini['magic_quotes_gpc']) . PHP_EOL;
echo
'(chargé ) magic_quotes_gpc = ' . yesno(get_cfg_var('magic_quotes_gpc')) . PHP_EOL;
?>

Résultat de l'exemple ci-dessus est similaire à :

(analysé) magic_quotes_gpc = Yes
(chargé ) magic_quotes_gpc = Yes

Exemple #4 Interpolation de Valeur

En plus d'évaluer les constantes, certains caractères ont une signification particulière dans une valeur ini. Additionnellement, les variables d'environment et options de configuration définies précédemment (voir get_cfg_var()) peuvent être lu en utilisant la syntaxe ${}.

; | is used for bitwise OR
three = 2|3

; & is used for bitwise AND
four = 6&5

; ^ is used for bitwise XOR
five = 3^6

; ~ is used for bitwise negate
negative_two = ~1

; () is used for grouping
seven = (8|7)&(6|5)

; Interpoler la variable d'environnement PATH
path = ${PATH}

; Interpoler l'option de configuration 'memory_limit'
configured_memory_limit = ${memory_limit}

Exemple #5 Échapper des Caractères

Certains caractères ont une signification particulière dans les chaînes à guillemets doubles et doivent être échappé en les préfixant d'un antislash. Tout d'abord, ce sont les guillemets double " comme le marqueur de frontière, et l'antislash \ lui-même (si suivit d'un des caractères spéciaux) :

quoted = "She said \"Exactly my point\"." ; Results in a string with quote marks in it.
hint = "Use \\\" to escape double quote" ; Results in: Use \" to escape double quote

Il y a une exception pour les chemins Windows-esque : il est possible de ne pas échapper l'antislash traînant si la chaîne cité est directement suivit d'un retour à la ligne :

save_path = "C:\Temp\"

Si l'on doit échapper une guillemet double suivit d'un retour à la ligne dans une valeur multiligne, il est possible d'utiliser la concaténation de valeur de la manière suivante (il y a une chaîne guillemet double directement suivit d'une autre) :

long_text = "Lorem \"ipsum\"""
 dolor" ; Results in: Lorem "ipsum"\n dolor

Un autre caractère avec une signification particulière est $ (le signe dollar). Il doit être échappé s'il est suivit d'une accolade ouvrante :

code = "\${test}"

L'échappement de caractères n'est pas supporté dans le mode INI_SCANNER_RAW (dans ce mode tous les caractères sont traité "tel quel").

Il est à noter que l'analyseur INI ne supporte pas les séquences d'échappement standard (\n, \t, etc.). Si nécessaire, le résultat de parse_ini_file() doit être post-procédé avec la fonction stripcslashes().

Notes

Note:

Cette fonction n'a rien a voir avec le fichier php.ini. Ce dernier a déjà été traité lorsque vous commencez à exécuter votre script. Cette fonction peut vous permettre de lire vos propres fichiers de configuration.

Note:

Si une valeur du fichier ini contient des données non-alphanumériques, il faut la protéger en la plaçant entre guillemets doubles (").

Note: Il existe des mots réservés qui ne doivent pas être utilisés en tant que clés dans les fichiers ini. Cela inclut : null, yes, no, true, false, on et off. Les valeurs null, off, no et false donnent "" (chaîne vide). Les valeurs on, yes et true donnent "1", à moins que le mode INI_SCANNER_TYPED ne soit utilisé. Les caractères ?{}|&~!()^" ne doivent pas être utilisés n'importe où dans la clé et ont une signification spéciale dans la valeur.

Note:

Les entrées sans un signal égal seront ignorées. Par exemple, "foo" sera ignoré alors que "bar =" sera analysé et ajouté avec une valeur vide. Par exemple, MySQL a une option de configuration "no-auto-rehash" dans le fichier my.cnf qui ne prend pas de valeur, aussi, elle sera ignorée.

Note:

Les fichiers ini sont généralement traité comme des fichiers de texte brut par les servers web, et donc envoyé au navigateur si demandé. Ceci signifie que pour la sécurité soit les fichiers ini doivent être stockés en dehors de la racine docroot, soit reconfigurer le serveur web pour ne pas les servir. L'échec de faire l'une de ces mesures peut introduire un risque de sécurité.

Voir aussi

add a note add a note

User Contributed Notes 15 notes

up
26
jeremygiberson at gmail dot com
14 years ago
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
*/
?>
up
11
Rekam
9 years ago
You may want, in some very special cases, to parse multi-dimensional array with N levels in your ini file. Something like setting[data][config][debug] = true will result in an error (expected "=").

Here's a little function to match this, using dots (customizable).
<?php
function parse_ini_file_multi($file, $process_sections = false, $scanner_mode = INI_SCANNER_NORMAL) {
   
$explode_str = '.';
   
$escape_char = "'";
   
// load ini file the normal way
   
$data = parse_ini_file($file, $process_sections, $scanner_mode);
    if (!
$process_sections) {
       
$data = array($data);
    }
    foreach (
$data as $section_key => $section) {
       
// loop inside the section
       
foreach ($section as $key => $value) {
            if (
strpos($key, $explode_str)) {
                if (
substr($key, 0, 1) !== $escape_char) {
                   
// key has a dot. Explode on it, then parse each subkeys
                    // and set value at the right place thanks to references
                   
$sub_keys = explode($explode_str, $key);
                   
$subs =& $data[$section_key];
                    foreach (
$sub_keys as $sub_key) {
                        if (!isset(
$subs[$sub_key])) {
                           
$subs[$sub_key] = [];
                        }
                       
$subs =& $subs[$sub_key];
                    }
                   
// set the value at the right place
                   
$subs = $value;
                   
// unset the dotted key, we don't need it anymore
                   
unset($data[$section_key][$key]);
                }
               
// we have escaped the key, so we keep dots as they are
               
else {
                   
$new_key = trim($key, $escape_char);
                   
$data[$section_key][$new_key] = $value;
                    unset(
$data[$section_key][$key]);
                }
            }
        }
    }
    if (!
$process_sections) {
       
$data = $data[0];
    }
    return
$data;
}
?>

The following file:
<?php
/*
[normal]
foo = bar
; use quotes to keep your key as it is
'foo.with.dots' = true

[array]
foo[] = 1
foo[] = 2

[dictionary]
foo[debug] = false
foo[path] = /some/path

[multi]
foo.data.config.debug = true
foo.data.password = 123456
*/
?>

will result in:
<?php
parse_ini_file_multi
('file.ini', true);

Array
(
    [
normal] => Array
        (
            [
foo] => bar
           
[foo.with.dots] => 1
       
)
    [array] => Array
        (
            [
foo] => Array
                (
                    [
0] => 1
                   
[1] => 2
               
)
        )
    [
dictionary] => Array
        (
            [
foo] => Array
                (
                    [
debug] =>
                    [
path] => /some/path
               
)
        )
    [
multi] => Array
        (
            [
foo] => Array
                (
                    [
data] => Array
                        (
                            [
config] => Array
                                (
                                    [
debug] => 1
                               
)
                            [
password] => 123456
                       
)
                )
        )
)
?>
up
8
simon dot riget at gmail dot com
11 years ago
.ini files or JSON file format as it is also known as, are very useful format to store stuff in. Especially large arrays.

Strangely enough there is this nice function to read the file, but no function to write it.

So here is one.

Use it as:  put_ini_file(string $file, array $array)

<?php
function put_ini_file($file, $array, $i = 0){
 
$str="";
  foreach (
$array as $k => $v){
    if (
is_array($v)){
     
$str.=str_repeat(" ",$i*2)."[$k]".PHP_EOL;
     
$str.=put_ini_file("",$v, $i+1);
    }else
     
$str.=str_repeat(" ",$i*2)."$k = $v".PHP_EOL;
  }
if(
$file)
    return
file_put_contents($file,$str);
  else
    return
$str;
}
?>
up
4
Justin Hall
17 years ago
This is a simple (but slightly hackish) way of avoiding the character limitations (in values):

<?php
define
('QUOTE', '"');
$test = parse_ini_file('test.ini');

echo
"<pre>";
print_r($test);
?>

contents of test.ini:

park yesterday = "I (walked) | {to} " QUOTE"the"QUOTE " park yesterday & saw ~three~ dogs!"

output:

<?php
Array
(
    [
park yesterday] => I (walked) | {to} "the" park yesterday & saw ~three~ dogs!
)
?>
up
2
dschnepper at box dot com
8 years ago
The documentation states:
Characters ?{}|&~!()^" must not be used anywhere in the key and have a special meaning in the value.

Here's the results of my experiments on what they mean:

; | is used for bitwise OR
three = 2|3

; & is used for bitwise AND
four = 6&5

; ^ is used for bitwise XOR
five = 3^6

; ~ is used for bitwise negate
negative_two = ~1

; () is used for grouping
seven = (8|7)&(6|5)

; ${...} is used for grabbing values from the environment, or previously defined values.
path = ${PATH}
also = ${five}

; ? I have no guess for
; ! I have no guess for
up
3
YAPs
7 years ago
This function for save ini files

<?php
function array_to_ini($array,$out="")
{
   
$t="";
   
$q=false;
    foreach(
$array as $c=>$d)
    {
        if(
is_array($d))$t.=array_to_ini($d,$c);
        else
        {
            if(
$c===intval($c))
            {
                if(!empty(
$out))
                {
                   
$t.="\r\n".$out." = \"".$d."\"";
                    if(
$q!=2)$q=true;
                }
                else
$t.="\r\n".$d;
            }
            else
            {   
               
$t.="\r\n".$c." = \"".$d."\"";
               
$q=2;
            }
        }
    }
    if(
$q!=true && !empty($out)) return "[".$out."]\r\n".$t;
    if(!empty(
$out)) return  $t;
    return
trim($t);
}

function
save_ini_file($array,$file)
{
   
$a=array_to_ini($array);
   
$ffl=fopen($file,"w");
   
fwrite($ffl,$a);
   
fclose($ffl);
}
?>
up
2
www.onphp5.com
16 years ago
Looks like in PHP 5.3.0 special characters like \n are extrapolated into real newlines. Gotta use \\n.
up
2
kieran dot huggins at rogers dot com
21 years ago
Just a quick note for all those running into trouble escaping double quotes:

I got around this by "base64_encode()"-ing my content on the way in to the ini file, and "base64_decode()"-ing on the way out.

Because base64 uses the "=" sign, you will have to encapsulate the entire value in double quotes so the line looks like this:

    varname = "TmlhZ2FyYSBGYWxscywgT04="

When base64'd, your strings will retain all \n, \t...etc...  URL's retain everything perfectly :-)

I hope some of you find this useful!

Cheers, Kieran
up
3
goulven.ch AT gmail DOT com
16 years ago
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.
*/
?>
up
1
info () gaj ! design
7 years ago
Not mentioned in the documentation, this function acts like include:

"Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include will finally check in the calling script's own directory and the current working directory before failing."

(At least for PHP 7; have not checked PHP 5.)
up
1
jbricci at ya-right dot com
8 years ago
This core function won't handle ini key[][] = value(s), (multidimensional arrays), so if you need to support that kind of setup you will need to write your own function. one way to do it is to convert all the key = value(s) to array string [key][][]=value(s), then use parse_str() to convert all those [key][][]=value(s) that way you just read the ini file line by line, instead of doing crazy foreach() loops to handle those (multidimensional arrays) in each section, example...

ini file...... config.php

<?php

; 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"

urls[svn] = "http://svn.php.net"
urls[git] = "http://git.php.net"

[fourth_section]

a[][][] = b
a
[][][][] = c
a
[test_test][][] = d
test
[one][two][three] = true

?>

echo parse_ini_file ( "C:\\services\\www\\docs\\config.php" );

results in...

// PHP Warning:  syntax error, unexpected TC_SECTION, expecting '=' line 27 -> a[][][] = b

Here it simple function that handles (multidimensional arrays) without looping each key[][]= value(s)

<?php

function getIni ( $file, $sections = FALSE )
{
   
$return = array ();

   
$keeper = array ();

   
$config = fopen ( $file, 'r' );

    while ( !
feof ( $config ) )
    {
       
$line = trim ( fgets ( $config, 1024 ) );

       
$line = ( $line == '' ) ? ' ' : $line;

        switch (
$line{0} )
        {
            case
' ':
            case
'#':
            case
'/':
            case
';':
            case
'<':
            case
'?':

            break;

            case
'[':

            if (
$sections )
            {
               
$header = 'config[' . trim ( substr ( $line, 1, -1 ) ) . ']';
            }
            else
            {
               
$header = 'config';
            }

            break;

            default:

           
$kv = array_map ( 'trim', explode ( '=', $line ) );

           
$kv[0] = str_replace ( ' ', '+', $kv[0] );

           
$kv[1] = str_replace ( ' ', '+', $kv[1] );

            if ( (
$pos = strpos ( $kv[0], '[' ) ) !== FALSE )
            {
               
$kv[0] = '[' . substr ( $kv[0], 0, $pos ) . ']' . substr ( $kv[0], $pos );
            }
            else
            {
               
$kv[0] = '[' . $kv[0] . ']';
            }

           
$bt = strtolower ( $kv[1] );

            if (
in_array ( $bt, array ( 'true', 'false', 'on', 'off' ) ) )
            {
               
$kv[1] = ( $bt == 'true' || $bt == 'on' ) ? TRUE : FALSE;
            }

           
$keeper[] = $header . $kv[0] . '=' . $kv[1];
        }
    }

   
fclose ( $config );

   
parse_str ( implode ( '&', $keeper ), $return );

    return
$return['config'];
}

// usage...

$sections = TRUE;

print_r ( $config->getIni ( "C:\\services\\www\\docs\\config.php" ),  $sections );

?>
up
1
dimk at pisem dot net
18 years ago
Class to access ini values at format "section_name.property", for example $myconf->get("system.name") returns a property "name" in section "system":

<?php
class Settings {

var
$properties = array();

    function
Settings() {
       
$this->properties = parse_ini_file(_SETTINGS_FILE, true);
    }

    function
get($name) {
        if(
strpos($name, ".")) {
            list(
$section_name, $property) = explode(".", $name);
           
$section =& $this->properties[$section_name];
           
$name = $property;
        } else {
           
$section =& $properties;
        }

        if(
is_array($section) && isset($section[$name])) {
            return
$section[$name];
        }
        return
false;
    }

}
?>
up
2
waikeatNOSPAM at archerlogic dot com
20 years ago
I found that this function will not work on remote files.
I tried

$someArray = parse_ini_file("http://www.example.com/setting.ini");

and it reports

Cannot Open 'http://www.example.com/setting.ini' for reading ...
up
0
Rubn Martnez
5 years ago
The parse_ini_file function does have trouble loading valid Windows ini files like, for example, nternet shortcuts (.url files).

This is due to the function reading the URLs as a value, and failing when it finds that valid URL characters like '=' appear unescaped or the value unquoted as a whole. Since Windows does not escape them anyway, the solution is to scan it in raw mode, where it will read unparsed the value after the first '='. Since = only appears in URLs with parameters, this mistake may is not be obvious at a first glance.

An example

<?php

$links
= array();

// ...

$files = scandir($directory);
foreach(
$files as $filename )
{
    if (
strToLower(pathinfo($filename, PATHINFO_EXTENSION)) === 'url')
    {
       
$shortcut = parse_ini_file( $directory.DIRECTORY_SEPARATOR.$filename, trueINI_SCANNER_RAW);
        if (
$shortcut === false) die('Syntax Error');
       
$url = $shortcut['InternetShortcut']['URL'];
       
$links []= $url;
    }
}

?>
up
0
yarco dot w at gmail dot com
16 years ago
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'));

?>
To Top