parse_ini_file

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

parse_ini_fileAnaliza un archivo de configuración

Descripción

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

parse_ini_file() carga el archivo filename y devuelve las configuraciones que contiene en forma de un array asociativo.

La estructura de los archivos de configuración leídos es similar a la de php.ini.

Parámetros

filename

El nombre del archivo de configuración a analizar. Si se utiliza una ruta relativa, se evalúa relativa a la carpeta actual, luego según el include_path.

process_sections

Al pasar el argumento process_sections a true, se obtendrá un array multidimensional con los nombres de las secciones. El valor por omisión de este argumento es false

scanner_mode

Puede ser INI_SCANNER_NORMAL (por omisión) o INI_SCANNER_RAW. Si se proporciona INI_SCANNER_RAW, entonces los valores en opción no serán analizados.

A partir de PHP 5.6.1 también se puede especificar como INI_SCANNER_TYPED. En este modo, los tipos boolean, null e integer se preservan siempre que sea posible. Los valores de string "true", "on" y "yes" son convertidos a true. "false", "off", "no" y "none" se consideran como false. "null" se convierte a null en el modo tipificado. También, todos los string numéricos son convertidos al tipo integer fuera es posible.

Valores devueltos

La configuración se devuelve en forma de un array asociativo en caso de éxito, y false si ocurre un error.

Ejemplos

Ejemplo #1 Contenido del archivo sample.ini

; Este es un archivo de configuración
; Los comentarios comienzan con ';', como en 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"

Ejemplo #2 Ejemplo con parse_ini_file()

Las constantes (pero no las "constantes mágicas" como __FILE__) también pueden ser utilizadas en el archivo .ini, por lo que si se define una constante antes de ejecutar parse_ini_file(), será integrada en los resultados. Solo se evalúan los valores de configuración, y el valor debe ser simplemente la constante. Por ejemplo:

<?php

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

// Análisis sin secciones
$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);

// Análisis con secciones
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);

?>

El resultado del ejemplo sería algo similar a:

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
                )

)

Ejemplo #3 parse_ini_file() para analizar un archivo php.ini

<?php
// Una función simple para comparar los resultados a continuación
function yesno($expression)
{
return(
$expression ? 'Yes' : 'No');
}

// Lee la ruta del php.ini utilizando php_ini_loaded_file()
$ini_path = php_ini_loaded_file();

// Análisis de php.ini
$ini = parse_ini_file($ini_path);

// Visualización y comparativo de los valores. Observe que get_cfg_var()
// dará los mismos resultados entre los resultados analizados y cargados
echo '(analizado) magic_quotes_gpc = ' . yesno($ini['magic_quotes_gpc']) . PHP_EOL;
echo
'(cargado ) magic_quotes_gpc = ' . yesno(get_cfg_var('magic_quotes_gpc')) . PHP_EOL;
?>

El resultado del ejemplo sería algo similar a:

(analizado) magic_quotes_gpc = Yes
(cargado ) magic_quotes_gpc = Yes

Ejemplo #4 Interpolación de Valor

Además de evaluar las constantes, ciertos caracteres tienen un significado particular en un valor ini. Adicionalmente, las variables de entorno y opciones de configuración definidas previamente (ver get_cfg_var()) pueden ser leídas utilizando la sintaxis ${}.

; | se utiliza para OR a nivel de bits
three = 2|3

; & se utiliza para AND a nivel de bits
four = 6&5

; ^ se utiliza para XOR a nivel de bits
five = 3^6

; ~ se utiliza para negación a nivel de bits
negative_two = ~1

; () se utiliza para agrupación
seven = (8|7)&(6|5)

; Interpolar la variable de entorno PATH
path = ${PATH}

; Interpolar la opción de configuración 'memory_limit'
configured_memory_limit = ${memory_limit}

Ejemplo #5 Escapar Caracteres

Ciertos caracteres tienen un significado particular en las cadenas entre comillas dobles y deben ser escapados prefijándolos con un antislash. Primero, son las comillas dobles " como marcador de frontera, y el antislash \ mismo (si está seguido de uno de los caracteres especiales):

quoted = "She said \"Exactly my point\"." ; Resultados en una cadena con marcas de comillas en ella.
hint = "Use \\\" to escape double quote" ; Resultados en: Use \" to escape double quote

Hay una excepción para las rutas estilo Windows: es posible no escapar el antislash final si la cadena citada es seguida directamente por un retorno de línea:

save_path = "C:\Temp\"

Si se debe escapar una comilla doble seguida de un retorno de línea en un valor multilínea, es posible utilizar la concatenación de valor de la siguiente manera (hay una cadena de comillas dobles seguida directamente de otra):

long_text = "Lorem \"ipsum\"""
 dolor" ; Resultados en: Lorem "ipsum"\n dolor

Otro carácter con un significado particular es $ (el signo de dólar). Debe ser escapado si está seguido de una llave abierta:

code = "\${test}"

El escape de caracteres no es soportado en el modo INI_SCANNER_RAW (en este modo todos los caracteres son tratados "tal cual").

Es de notar que el analizador INI no soporta las secuencias de escape estándar (\n, \t, etc.). Si es necesario, el resultado de parse_ini_file() debe ser post-procesado con la función stripcslashes().

Notas

Nota:

Esta función no tiene nada que ver con el archivo php.ini. Este último ya ha sido procesado cuando se comienza a ejecutar el script. Esta función puede permitir leer sus propios archivos de configuración.

Nota:

Si un valor del archivo ini contiene datos no-alfanuméricos, debe ser protegido colocándolo entre comillas dobles (").

Nota: Existen palabras reservadas que no deben ser utilizadas como claves en los archivos ini. Esto incluye: null, yes, no, true, false, on y off. Los valores null, off, no y false dan "" (cadena vacía). Los valores on, yes y true dan "1", a menos que se utilice el modo INI_SCANNER_TYPED. Los caracteres ?{}|&~!()^" no deben ser utilizados en ninguna parte de la clave y tienen un significado especial en el valor.

Nota:

Las entradas sin un signo igual serán ignoradas. Por ejemplo, "foo" será ignorado mientras que "bar =" será analizado y añadido con un valor vacío. Por ejemplo, MySQL tiene una opción de configuración "no-auto-rehash" en el archivo my.cnf que no toma valor, por lo tanto, será ignorada.

Nota:

Los archivos ini son generalmente tratados como archivos de texto sin formato por los servidores web, y por lo tanto enviados al navegador si se solicita. Esto significa que para la seguridad, los archivos ini deben ser almacenados fuera de la raíz docroot, o reconfigurar el servidor web para no servirlos. El fracaso de realizar una de estas medidas puede introducir un riesgo de seguridad.

Ver también

add a note

User Contributed Notes 13 notes

up
34
jeremygiberson at gmail dot com
16 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
3
theking2(at)king.ma
1 year ago
To make the content available in every corner of you application I use a user defined constant. $SETTINGS. It is initialized like this
<?php

define
( 'SETTINGS", parse_ini_file('settings.ini', true) );

?>
With the proper settings.ini file you can now do stuff like
<?php
$db = new \PDO(
"mysql:host={SETTINGS['
db']['host']};dbname={SETTINGS['db']['name']};charset=utf8",
SETTINGS['
db']['user'],
SETTINGS['
db']['pass'], [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
]
);
?>

Make sure to hide your settings.ini file on a website with for instance
<?php
<FilesMatch "\.(?:ini|htaccess)$">
Order allow,deny
Deny from all
</FilesMatch>
?>
up
14
Rekam
11 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
4
dschnepper at box dot com
9 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
info () gaj ! design
8 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
4
YAPs
8 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
4
goulven.ch AT gmail DOT com
17 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
4
Justin Hall
18 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
4
simon dot riget at gmail dot com
12 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
1
kieran dot huggins at rogers dot com
22 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
1
eciruam35 at gmail dot com
1 year ago
fix a little bug (here) in function put_ini_file:

function put_ini_file($config, $file, $has_section = false, $write_to_file = true){
$fileContent = '';
if(!empty($config)){
foreach($config as $i=>$v){
if($has_section){
$fileContent .= "\n[$i]".PHP_EOL.put_ini_file($v, $file, false, false);
}
else{
if(is_array($v)){
foreach($v as $t=>$m){
//--->>> Here $fileContent .= "-->$i[$t] = ".(is_numeric($m) ? $m : '"'.$m.'"').PHP_EOL;
$fileContent .= "$i"."[] = ".(is_numeric($m) ? $m : '"'.$m.'"').PHP_EOL;
}
}
else $fileContent .= "$i = ".(is_numeric($v) ? $v : '"'.$v.'"').PHP_EOL;
}
}
}

if($write_to_file && strlen($fileContent)) return file_put_contents($file, $fileContent, LOCK_EX);
else return $fileContent;
}
up
0
manngo
1 year ago
Securing your .ini file:

“ini files are generally treated as plain text by web servers and thus served to browsers if requested. That means for security you must either keep your ini files outside of your docroot or reconfigure your web server to not serve them. Failure to do either of those may introduce a security risk.”

Alternatively, you can save you file as:

stuff.ini.php

add this to the beginning:

;<?php die('go away'); ?>

The semicolon at the beginning is treated as comment, so this line has no effect on the ini file.

Since the file has a .php extension, it will run through the PHP interpreter if you attempt to access this file directly, and the php block will be processed and exit.

The file extension has no ill effect on the parse_ini_file() function, and the .ini part is, of course, a matter of taste.
up
0
jbricci at ya-right dot com
9 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 );

?>
To Top