基本上,我想要一个简单,简单,单文件的方法来解析具有“高级”功能的INI文件,例如部分继承和属性嵌套,如Zend_Config_Ini。
例如:
[foo]
a = 1
b.a = 2
b.b = 3
b.c = 4
c = 5
[bar : foo]
b.b = 17
c = 42
将解析
array(
'foo'=>array(
'a'=>'1',
'b'=>array(
'a'=>'2',
'b'=>'3',
'c'=>'4'
),
'c'=>'5'
),
'bar'=>array(
'a'=>'1',
'b'=>array(
'a'=>'2',
'b'=>'17',
'c'=>'4'
),
'c'=>'42'
)
)
PHP的内置parse_ini_file
除了使用简单的部分和简单的键之外,不会处理简单的INI以外的任何内容。
使用Zend_Config_Ini
的问题在于我必须包含几乎整个Zend_Config子包,并且超级膨胀且可配置。
是否有 small 和简单库可用于解析此问题?
如果没有,是否有 easy 实现,我没有看到?
小而简单,我的意思是像INI文件的sfYaml。
对于我(非常缺乏经验)的眼睛,我将不得不用parse_ini_file
解析一次,然后返回并解决继承,然后遍历每个部分并递归扩展键...
更新:由于这似乎是一个受欢迎的问题,我想注意I have a simple class implementing this on GitHub,随时发送拉请求,问题等。
答案 0 :(得分:16)
不确定我是否应该编辑旧答案或添加新答案。
试试这个版本,应该是你想要的。
function parse_ini_advanced($array) {
$returnArray = array();
if (is_array($array)) {
foreach ($array as $key => $value) {
$e = explode(':', $key);
if (!empty($e[1])) {
$x = array();
foreach ($e as $tk => $tv) {
$x[$tk] = trim($tv);
}
$x = array_reverse($x, true);
foreach ($x as $k => $v) {
$c = $x[0];
if (empty($returnArray[$c])) {
$returnArray[$c] = array();
}
if (isset($returnArray[$x[1]])) {
$returnArray[$c] = array_merge($returnArray[$c], $returnArray[$x[1]]);
}
if ($k === 0) {
$returnArray[$c] = array_merge($returnArray[$c], $array[$key]);
}
}
} else {
$returnArray[$key] = $array[$key];
}
}
}
return $returnArray;
}
function recursive_parse($array)
{
$returnArray = array();
if (is_array($array)) {
foreach ($array as $key => $value) {
if (is_array($value)) {
$array[$key] = recursive_parse($value);
}
$x = explode('.', $key);
if (!empty($x[1])) {
$x = array_reverse($x, true);
if (isset($returnArray[$key])) {
unset($returnArray[$key]);
}
if (!isset($returnArray[$x[0]])) {
$returnArray[$x[0]] = array();
}
$first = true;
foreach ($x as $k => $v) {
if ($first === true) {
$b = $array[$key];
$first = false;
}
$b = array($v => $b);
}
$returnArray[$x[0]] = array_merge_recursive($returnArray[$x[0]], $b[$x[0]]);
} else {
$returnArray[$key] = $array[$key];
}
}
}
return $returnArray;
}
会像这样调用:
$array = parse_ini_file('test.ini', true);
$array = recursive_parse(parse_ini_advanced($array));
这可以做得更好/更清楚,但对于一个简单的解决方案,它应该可以正常工作。
如果你的配置是:
[foo]
a = 1
b.a = 2
b.b = 3
b.c = 4
c = 5
[bar : foo]
b.x.c = 33
b.b = 17
c = 42
[hot : bar : foo]
b.a = 83
b.d = 23
输出应为:
Array
(
[foo] => Array
(
[a] => 1
[b] => Array
(
[a] => 2
[b] => 3
[c] => 4
)
[c] => 5
)
[bar] => Array
(
[a] => 1
[b] => Array
(
[a] => 2
[b] => 17
[c] => 4
[x] => Array
(
[c] => 33
)
)
[c] => 42
)
[hot] => Array
(
[a] => 1
[b] => Array
(
[a] => 83
[b] => 17
[c] => 4
[x] => Array
(
[c] => 33
)
[d] => 23
)
[c] => 42
)
)
答案 1 :(得分:3)
首先回答一件事,属性嵌套可以从parse_ini_file()中获取,将第二个param设置为true,即parse_ini_file('test.ini',true);那会给你一个多维数组,即
Array
(
[foo] => Array
(
[a] => 1
[b.a] => 2
[b.b] => 3
[b.c] => 4
[c] => 5
)
[bar : foo] => Array
(
[b.b] => 17
[c] => 42
)
)
这是一个小函数,它将解析parse_ini_file()返回的数组并将其转换为类别。
/**
* Parse INI files Advanced
* process_sections = true
* scanner_mode = default
*
* Supports section inheritance
* and has property nesting turned on
*
* @param string $filename
* return array
*/
function parse_ini_file_advanced($filename) {
$array = parse_ini_file($filename, true);
$returnArray = array();
if (is_array($array)) {
foreach ($array as $key => $value) {
$x = explode(':', $key);
if (!empty($x[1])) {
$x = array_reverse($x, true);
foreach ($x as $k => $v) {
$i = trim($x[0]);
$v = trim($v);
if (empty($returnArray[$i])) {
$returnArray[$i] = array();
}
if (isset($array[$v])) {
$returnArray[$i] = array_merge($returnArray[$i], $array[$v]);
}
if ($k === 0) {
$returnArray[$i] = array_merge($returnArray[$i], $array[$key]);
}
}
} else {
$returnArray[$key] = $array[$key];
}
}
} else {
return false;
}
return $returnArray;
}
它会返回:
Array
(
[foo] => Array
(
[a] => 1
[b.a] => 2
[b.b] => 3
[b.c] => 4
[c] => 5
)
[bar] => Array
(
[a] => 1
[b.a] => 2
[b.b] => 17
[b.c] => 4
[c] => 42
)
)
最后写作获胜,即
[bar2:foo2:bar:foo]
bar2在它自己的阵列中使用它的设置获胜
注意:其他3个阵列将在那时进行。
希望这就是你要找的东西。
答案 2 :(得分:0)
我写过类似的东西,现在它对我有用了:
$config = array();
$configSrc = parse_ini_file( $filePath, true );
foreach( $configSrc as $sectionName => $section )
{
$config[$sectionName] = array();
foreach( $section as $itemName => $item )
{
$itemNameArray = explode( '.', $itemName );
eval( sprintf('$config[$sectionName][\'%s\'] = $item;', join("']['", $itemNameArray)) );
}
}
// marge inheritance;
foreach( $config as $sectionName => $section )
{
$ancestryArray = explode( ':', $sectionName );
$ancestryCount = count( $ancestryArray );
if( $ancestryCount > 1 )
{ //
$config[$sectionNameTrimmed = trim($ancestryArray[0])] = array();
$ancestryArray = array_reverse( array_slice($ancestryArray, 1) );
foreach( $ancestryArray as $ancestryName )
{
$ancestryName = trim( $ancestryName );
if( isset($config[$ancestryName]) ) {
$config[$sectionNameTrimmed] = array_replace_recursive( $config[$sectionNameTrimmed], $config[$ancestryName] );
}
}
$config[$sectionNameTrimmed] = array_replace_recursive( $config[$sectionNameTrimmed], $section );
unset( $config[$sectionName] );
}
}
答案 3 :(得分:0)
另一种选择 - 这是对,构建和解析。
function build_ini_string_nested( $data, $path = null ){
$content = array();
foreach( $data AS $key => $val ){
if( is_array($val) ){
$content[] = build_ini_string_nested( $val, ($path ? $path. '.' : '') . $key );
}
else if( $path ) {
$content[] = $path . '[' . ($path && is_numeric($key) ? '' : $key) . '] = ' . $val;
}
else {
$content[] = $key . ' = ' . $val;
}
}
return implode("\n", $content);
}
function parse_ini_string_nested( $data, $path = null ){
if( is_string($data) )
$data = parse_ini_string($data);
if( $path )
foreach( $data AS $key => $val ){
if( strpos( $key, $path.'.' ) !== false ){
$find_node = explode('.', $path);
$this_path = reset(explode('.', substr($key, strlen($path.'.'))));
$node =& $data;
do {
$node =& $node[ array_shift($find_node) ];
} while( count($find_node) );
if( is_array($node[ $this_path ]) ){
$node[ $this_path ][] = $val;
}
else {
$node[ $this_path ] = $val;
}
}
}
else {
$drop_keys = array();
foreach( $data AS $key => $val ){
if( count(explode('.', $key)) > 1 ){
$path = reset(explode('.', $key));
$data[ $path ] = array();
$data = parse_ini_string_nested( $data, $path );
$drop_keys[] = $key;
}
}
foreach( $drop_keys AS $key ){
unset($data[ $key ]);
}
}
return $data;
}