Парсинг “усовершенствованного” файла INI с PHP

В основном я хотел бы простой, легкий, способ с одним файлом проанализировать файл 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's parse_ini_file, ничего не обрабатывает кроме простого INI's с простыми разделами и простыми ключами.

Моя проблема с использованием Zend_Config_Ini это, я должен был бы включать фактически целый подпакет Zend_Config, и суперчрезмерно увеличен в размере и настраиваюсь.

Существует ли небольшая и простая библиотека, доступная для парсинга этого?
В противном случае существует ли простое внедрение, которое я не вижу?

Маленьким и простым, я имею в виду что-то как sfYaml файлов INI.

К моим (очень неопытным) глазам я должен был бы проанализировать до однажды с parse_ini_file, затем возвратитесь и разрешите наследование, затем пробегите каждый раздел и разверните ключи рекурсивно...

ОБНОВЛЕНИЕ: Так как это, кажется, популярный вопрос, я хотел бы отметить, что у меня есть простой класс, реализовывая это на GitHub, не стесняйтесь отправлять запросы получения по запросу, проблемы, и т.д.

12
задан Austin Hyde 29 June 2012 в 13:17
поделиться

2 ответа

Не уверен, должен ли я редактировать свой старый ответ или добавить новый.

Попробуйте эту версию, это должно быть то, что вы ищете.

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
    )
)
16
ответ дан 2 December 2019 в 18:51
поделиться

Прежде всего, чтобы ответить на один вопрос, вложение свойств доступно из parse_ini_file (), установите для второго параметра значение 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 массива БУДУТ там до этого момента.

Надеюсь, это было то, что вы искали.

3
ответ дан 2 December 2019 в 18:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: