CakeFest 2024: The Official CakePHP Conference

parse_ini_file

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

parse_ini_fileInterpreta um arquivo de configuração

Descrição

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

parse_ini_file() carrega o arquivo INI especificado em filename e retorna as configurações contidas nele em um array associativo.

A estrutura do arquivo INI é a mesma do php.ini.

Parâmetros

filename

O nome do arquivo INI sendo interpretado. Se um caminho relativo for usado, será avaliado relativamente ao diretório atual de trabalho, e depois no caminho include_path.

process_sections

Definindo o parâmetro process_sections para true, obtém-se um array multidimensional com os nomes das seções e configurações incluídos. O padrão para process_sections é false

scanner_mode

Pode ser INI_SCANNER_NORMAL (padrão) ou INI_SCANNER_RAW. Se INI_SCANNER_RAW for fornecido, os valores das opções não serão interpretados.

A partir do PHP 5.6.1, também pode ser especificado como INI_SCANNER_TYPED. Nesse modo, os tipos boolean, null e integer são preservados quando possível. Os valores string "true", "on" e "yes" são convertidos em true. "false", "off", "no" e "none" são considerados false. "null" é convertido para null no modo tipado. Além disso, todas as strings numéricas são convertidas para o tipo inteiro, se possível.

Valor Retornado

As configurações são retornadas como um array associativo em caso de sucesso, and false on failure.

Exemplos

Exemplo #1 Conteúdo de sample.ini

; Este é um arquivo de configuração de exemplo
; Comentários iniciam com ';', como no php.ini

[primeira_secao]
um = 1
cinco = 5
animal = PASSARO

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

[terceira_secao]
versaophp[] = "5.0"
versaophp[] = "5.1"
versaophp[] = "5.2"
versaophp[] = "5.3"

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

Exemplo #2 Exemplo de parse_ini_file()

Constantes (mas não "constantes mágicas" como __FILE__) também podem ser interpretadas no arquivo INI. Se for definida uma constante como um valor INI antes de executar parse_ini_file(), ela será intergrada aos resultados. Somente valores INI são avaliados e o valor deve ser apenas a constante. Por exemplo:

<?php

define
('PASSARO', 'Pássaro Dodo');

// Interpreta sem as seções
$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);

// Interpreta com as seções
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);

?>

O exemplo acima produzirá algo semelhante a:

Array
(
    [um] => 1
    [cinco] => 5
    [animal] => Pássaro Dodo
    [path] => /usr/local/bin
    [URL] => http://www.example.com/~username
    [versaophp] => 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
(
    [primeira_secao] => Array
        (
            [um] => 1
            [cinco] => 5
            [animal] = Pássaro Dodo
        )

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

    [terceira_secao] => Array
        (
            [versaophp] => 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
                )

        )

)

Exemplo #3 parse_ini_file() interpretando um arquivo php.ini

<?php
// Uma função simples usada para comparar os resultados abaixo
function sim_nao($expression)
{
return(
$expression ? 'Sim' : 'Não');
}

// Obtém o caminho para o php.ini usando a função php_ini_loaded_file()
$ini_path = php_ini_loaded_file();

// Interpreta o php.ini
$ini = parse_ini_file($ini_path);

// Mostra e compara os valores, note que usar get_cfg_var()
// levará aos mesmos resultados para interpretado e carregado aqui
echo '(interpretado) magic_quotes_gpc = ' . sim_nao($ini['magic_quotes_gpc']) . PHP_EOL;
echo
'(carregado) magic_quotes_gpc = ' . sim_nao(get_cfg_var('magic_quotes_gpc')) . PHP_EOL;
?>

O exemplo acima produzirá algo semelhante a:

(parsed) magic_quotes_gpc = Sim
(loaded) magic_quotes_gpc = Sim

Exemplo #4 Interpolação de Valor

Além de avaliar constantes, alguns caracteres possuem significado especial em um valor INI. Adicionamente, variáveis de ambiente e opções de configuração previamente definidas (consulte get_cfg_var()) podem ser lidas usando a sintaxe ${}.

; | é usado par OR bit a bit
tres = 2|3

; & é usado para AND bit a bit
quatro = 6&5

; ^ é usado para XOR bit a bit
cinco = 3^6

; ~ é usado para inversão bit a bit
dois_negativo = ~1

; () é usado para agrupamento
sete = (8|7)&(6|5)

; Interpola a variável de ambiente PATH
path = ${PATH}

; Interpola a opção de configuração 'memory_limit'
limite_de_memoria_configurado = ${memory_limit}

Exemplo #5 Fazendo Escape de Caracteres

Alguns caracteres têm significado especial em strings com aspas duplas e devem ser escapados pela barra invertida prefixada. Primeiramente, eles são as aspas duplas " como marcação dos limites, e a barra invertida \ em si (se seguida por um dos caracteres especiais):

fala = "Ela disse \"Exatamente meu ponto\"." ; Resulta em uma string contendo aspas duplas.
dica = "Use \\\" para escapar aspas duplas" ; Resulta em: Use \" para escapar aspas duplas

Há uma excecão feita para caminhos do tipo Windows: é possível não escapar barra invertida no final se a string entre aspas for diretamente seguida por uma quebra de linha:

save_path = "C:\Temp\"

Se for necessário escapar aspas duplas seguidas pode quebra de linha em um valor com várias linhas, é possível usar concatenação de valores da seguinte forma (há uma string com aspas duplas diretamente seguida por outra):

long_text = "Lorem \"ipsum\"""
 dolor" ; Resulta em: Lorem "ipsum"\n dolor

Outro caractere com significado especial é $ (sinal de cifrão). Deve ser escapado se for seguido de chave:

code = "\${test}"

Escapar caracteres não é suportado no modo INI_SCANNER_RAW (neste modo todos os caracateres são processados como eles são).

Note que o interpretador INI não suporta sequências escape padrões (\n, \t etc.). Se necessário, faça pós processamento do resultado de parse_ini_file() com a função stripcslashes().

Notas

Nota:

Essa função não tem relação nenhuma com o arquivo php.ini. Ele já está processado no momento em o script é executado. Esta função pode ser usada para ler os arquivos de configuração da própria aplicação do usuário.

Nota:

Se um valor no arquivo INI tiver algum caractere não alfanumérico, ele precisará ser envolvido em aspas duplas (").

Nota: Existem algumas palavras reservadas que não podem ser usadas como chaves em arquivos INI. Elas incluem: null, yes, no, true, false, on, off e none. Valores null, off, no e false resultam em "", e os valores on, yes e true resultam em "1", a menos que o modo INI_SCANNER_TYPED seja usado. Os caracteres ?{}|&~!()^" não devem ser usados em nenhum lugar da chave e têm um significado especial no valor.

Nota:

Entradas sem um sinal de igualdade são ignoradas. Por exemplo, "foo" é ignorado enquanto que "bar =" é interpretado e adicionado com um valor vazio. Por exemplo, o MySQL tem uma configuração "no-auto-rehash" no arquivo my.cnf que não leva um valor, portanto ela é ignorada.

Nota:

Arquivos INI são feralmente tratados como texto puro por servidores web e depois enviados aos navegadores se requisitados. Isto quer dizer que para segurança deve-se manter os arquivos INI fora da raiz de documentos da web ou reconfigurar seu servidor web para não disponibilizá-los. Falha em fazer isso pode introduzir um risco de segurança.

Veja Também

add a note

User Contributed Notes 13 notes

up
29
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
13
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
4
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
5
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
3
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
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
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
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
5
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
1
theking2(at)king.ma
1 month 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
1
eciruam35 at gmail dot com
6 months 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
4 months 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
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 );

?>
To Top