parse_ini_file

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

parse_ini_file解析配置文件

描述

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

parse_ini_file() 加载 filename 中指定的 ini 文件,并将其中的设置以关联数组形式返回。

ini 文件的结构与 php.ini 的结构相同。

参数

filename

要解析的 ini 文件的文件名。如果使用相对路径,则相对于当前工作目录进行评估,然后是 include_path

process_sections

process_sections 参数设置为 true,则会获得一个多维数组,其中包含节名称和设置。 process_sections 的默认值为 false

scanner_mode

可以是 INI_SCANNER_NORMAL(默认)或 INI_SCANNER_RAW。如果提供 INI_SCANNER_RAW,则选项值不会被解析。

从 PHP 5.6.1 开始,还可以指定为 INI_SCANNER_TYPED。在此模式下,布尔型、空值和整型类型会在可能的情况下被保留。字符串值 "true""on""yes" 将被转换为 true"false""off""no""none" 被视为 false"null" 在类型化模式下被转换为 null。此外,所有数字字符串都将尽可能地转换为整型。

返回值

成功时,设置将以关联 array 形式返回,失败时返回 false

示例

示例 #1 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"

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

示例 #2 parse_ini_file() 示例

常量(但不是像 __FILE__ 这样的“魔术常量”)也可以在 ini 文件中解析,因此如果您在运行 parse_ini_file() 之前定义常量作为 ini 值,它将被集成到结果中。只有 ini 值会被评估,并且该值必须只是常量。例如

<?php

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

// 解析不带节
$ini_array = parse_ini_file("sample.ini");
print_r($ini_array);

// 解析带节
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);

?>

上面的示例将输出类似于以下内容的内容

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
                )

        )

)

示例 #3 parse_ini_file() 解析 php.ini 文件

<?php
// 用于比较下面结果的简单函数
function yesno($expression)
{
return(
$expression ? 'Yes' : 'No');
}

// 使用 php_ini_loaded_file() 函数获取 php.ini 的路径
$ini_path = php_ini_loaded_file();

// 解析 php.ini
$ini = parse_ini_file($ini_path);

// 打印并比较值,注意使用 get_cfg_var()
// 将为此处解析和加载的结果提供相同的结果
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;
?>

上面的示例将输出类似于以下内容的内容

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

示例 #4 值插值

除了评估常量之外,某些字符在 ini 值中具有特殊含义。此外,环境变量和先前定义的配置选项(请参阅 get_cfg_var())可以使用 ${} 语法读取。

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

; Interpolate the PATH environment variable
path = ${PATH}

; Interpolate the configuration option 'memory_limit'
configured_memory_limit = ${memory_limit}

示例 #5 转义字符

某些字符在双引号字符串中具有特殊含义,必须通过反斜杠前缀转义。首先,这些是作为边界标记的双引号 " 和反斜杠 \ 本身(如果后跟特殊字符之一)

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

对 Windows 风格的路径有一个例外:如果引号字符串紧接在换行符之后,则可以不转义尾随反斜杠

save_path = "C:\Temp\"

如果确实需要在多行值中转义双引号后跟换行符,可以使用以下方式进行值连接(一个双引号字符串紧接在另一个双引号字符串之后)

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

另一个具有特殊含义的字符是 $(美元符号)。如果后跟左大括号,则必须转义它

code = "\${test}"

INI_SCANNER_RAW 模式下不支持转义字符(在此模式下,所有字符都“按原样”处理)。

请注意,ini 解析器不支持标准转义序列(\n\t 等)。如果需要,请使用 stripcslashes() 函数对 parse_ini_file() 的结果进行后处理。

注释

注意:

此函数与 php.ini 文件无关。在您运行脚本之前,它已经过处理。此函数可用于读取您自己的应用程序的配置文件。

注意:

如果 ini 文件中的值包含任何非字母数字字符,则需要将其括在双引号 (") 中。

注意: 有些保留字不能用作 ini 文件的键。这些包括:nullyesnotruefalseonoffnone。除非使用 INI_SCANNER_TYPED 模式,否则值 nulloffnofalse 会导致 "",而值 onyestrue 会导致 "1"。字符 ?{}|&~!()^" 不能在键中使用,并且在值中具有特殊含义。

注意:

没有等号的条目会被忽略。例如,“foo”会被忽略,而“bar =”会被解析并添加一个空值。例如,MySQL 在 my.cnf 中有一个“no-auto-rehash”设置,它不接受任何值,因此会被忽略。

注意:

ini 文件通常被 Web 服务器视为纯文本,因此如果请求,它们会提供给浏览器。这意味着出于安全考虑,您必须将 ini 文件保存在您的 docroot 之外,或者重新配置您的 Web 服务器以不提供它们。如果未执行其中任何一项操作,可能会存在安全风险。

参见

添加说明

用户贡献说明 13 条说明

jeremygiberson at gmail dot com
15 年前
这是一个快速 parse_ini_file 包装器,用于添加扩展支持以节省输入和冗余。
<?php
/**
* 解析 INI 文件,通过命名空间上的 ":base" 后缀添加扩展功能。
*
* @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);
// 必要时创建命名空间
if(!isset($config[$name])) $config[$name] = array();
// 继承基本命名空间
if(isset($p_ini[$extends])){
foreach(
$p_ini[$extends] as $prop => $val)
$config[$name][$prop] = $val;
}
// 覆盖/设置当前命名空间值
foreach($properties as $prop => $val)
$config[$name][$prop] = $val;
}
return
$config;
}
?>

将此 ini 文件
<?php
/*
[base]
host=localhost
user=testuser
pass=testpass
database=default

[users:base]
database=users

[archive : base]
database=archive
*/
?>
视为类似这样
<?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
*/
?>
Rekam
10 年前
在某些非常特殊的情况下,您可能希望在您的 ini 文件中解析具有 N 级别的多维数组。例如,设置[data][config][debug] = true 会导致错误(预期“=”)。

以下是一个使用点(可自定义)来匹配此功能的小函数。
<?php
function parse_ini_file_multi($file, $process_sections = false, $scanner_mode = INI_SCANNER_NORMAL) {
$explode_str = '.';
$escape_char = "'";
// 以正常方式加载 ini 文件
$data = parse_ini_file($file, $process_sections, $scanner_mode);
if (!
$process_sections) {
$data = array($data);
}
foreach (
$data as $section_key => $section) {
// 循环遍历节区内部
foreach ($section as $key => $value) {
if (
strpos($key, $explode_str)) {
if (
substr($key, 0, 1) !== $escape_char) {
// 键包含点。按此分割,然后解析每个子键
// 并使用引用在正确的位置设置值
$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];
}
// 在正确的位置设置值
$subs = $value;
// 取消设置带点的键,我们不再需要它
unset($data[$section_key][$key]);
}
// 我们已经转义了键,因此我们将点保留原样
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;
}
?>

以下文件
<?php
/*
[normal]
foo = bar
; 使用引号保留键的原始形式
'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
*/
?>

将生成以下结果
<?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
)
)
)
)
?>
dschnepper at box dot com
8 年前
文档中说明
字符 ?{}|&~!()^" 不得在键中使用,它们在值中具有特殊含义。

以下是我对它们含义进行实验的结果

; | 用于按位或运算
three = 2|3

; & 用于按位与运算
four = 6&5

; ^ 用于按位异或运算
five = 3^6

; ~ 用于按位取反
negative_two = ~1

; () 用于分组
seven = (8|7)&(6|5)

; ${...} 用于从环境中获取值,或获取先前定义的值。
path = ${PATH}
also = ${five}

; ? 我无法猜测
; ! 我无法猜测
YAPs
8 年前
此函数用于保存 ini 文件

<?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);
}
?>
info () gaj ! design
7 年前
文档中未提及,此函数的行为类似于 include

"文件包含基于给定的文件路径,或者,如果没有给出,则基于指定的 include_path。 如果在 include_path 中找不到文件,include 最终将在调用脚本的自身目录和当前工作目录中检查,然后才会失败。"

(至少对于 PHP 7;未检查 PHP 5。)
kieran dot huggins at rogers dot com
21 年前
对于所有遇到双引号转义问题的人,快速提醒一下

我通过在写入 ini 文件时对内容进行 "base64_encode()" 编码,并在读取时进行 "base64_decode()" 解码来解决这个问题。

由于 base64 使用 "=" 符号,您必须将整个值用双引号括起来,使行看起来像这样

varname = "TmlhZ2FyYSBGYWxscywgT04="

在进行 base64 编码后,您的字符串将保留所有 \n,\t...等等... URL 完美保留一切 :-)

希望对大家有所帮助!

致敬,Kieran
Justin Hall
17 年前
这是一种简单(但略微技巧性)的方式来避免字符限制(在值中)

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

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

test.ini 文件内容

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

输出

<?php
Array
(
[
park yesterday] => I (walked) | {to} "the" park yesterday & saw ~three~ dogs!
)
?>
goulven.ch AT gmail DOT com
16 年前
警告:parse_ini_files 无法处理包含等号 (=) 的值。

以下函数支持节、注释、数组以及任何节之外的键值对。
请注意,类似的键会互相覆盖(除非它们位于不同的节中)。

<?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 );
// 注释
if ( $line == '' || $line{0} == ';' ) { continue; }
// 节
if ( $line{0} == '[' ) {
$sections[] = substr( $line, 1, -1 );
$i++;
continue;
}
// 键值对
list( $key, $value ) = explode( '=', $line, 2 );
$key = trim( $key );
$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++ ) {
$result[ $sections[ $j ] ] = $values[ $j ];
}
return
$result + $globals;
}
?>

示例用法
<?php
$stores
= parse_ini('stores.ini');
print_r( $stores );
?>

示例 ini 文件
<?php
/*
; 注释行以 ';' 开头
global_value1 = a string value
global_value1 = another string value

; 空行被丢弃
[Section1]
key = value
; 键和值周围的空格也会被丢弃
otherkey=other value
otherkey=yet another value
; 此键值对将覆盖前面的键值对。
*/
?>
simon dot riget at gmail dot com
11 年前
.ini 文件或 JSON 文件格式(也称为 JSON 文件格式)是一种非常实用的存储数据的格式。 尤其适用于大型数组。

奇怪的是,有一个读取文件的好用函数,却没有写入文件的函数。

所以这里有一个。

用法: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;
}
?>
theking2(at)king.ma
5 个月前
为了使内容在应用程序的每个角落都可用,我使用了一个用户定义的常量。 $SETTINGS。 它初始化如下
<?php

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

?>
有了正确的 settings.ini 文件,你就可以做以下事情了
<?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
]
);
?>

确保在网站上隐藏你的 settings.ini 文件,例如
<?php
<FilesMatch "\.(?:ini|htaccess)$">
Order allow,deny
Deny from all
</FilesMatch>
?>
eciruam35 at gmail dot com
10 个月前
修复了 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){
//--->>> 此处 $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;
}
manngo
9 个月前
保护你的 .ini 文件

“ini 文件通常被 web 服务器视为纯文本,因此如果被请求,它们会被提供给浏览器。 这意味着出于安全考虑,你必须将你的 ini 文件保存在你的 docroot 之外,或者重新配置你的 web 服务器使其不提供它们。 如果没有执行这两者中的任何一项,可能会引入安全风险。”

或者,你可以将文件保存为

stuff.ini.php

在开头添加以下内容

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

开头处的分号被视为注释,因此此行对 ini 文件没有影响。

由于该文件具有 .php 扩展名,因此如果你尝试直接访问此文件,它将通过 PHP 解释器运行,并且 php 块将被处理并退出。

文件扩展名对 parse_ini_file() 函数没有不良影响,而 .ini 部分当然只是一个个人喜好问题。
jbricci at ya-right dot com
8 年前
这个核心函数不会处理 ini key[][] = value(s)(多维数组),因此如果你需要支持这种设置,你需要编写自己的函数。 一种方法是将所有 key = value(s) 转换为数组字符串 [key][][]=value(s),然后使用 parse_str() 将所有这些 [key][][]=value(s) 转换过来,这样你只需逐行读取 ini 文件,而不是使用疯狂的 foreach() 循环来处理每个部分中的这些(多维数组),例如...

ini 文件...... config.php

<?php

; 这是一个示例配置文件
; 注释以 ';' 开头,就像 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" );

结果是...

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

这里有一个简单的函数,它处理(多维数组),而无需循环每个 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