Использование ключевого слова в качестве имени переменной в файле INI - PullRequest
7 голосов
/ 26 мая 2011

У меня есть следующее в INI-файле:

[country]
SE = Sweden
NO = Norway
FI = Finland

Однако, когда var_dump () использует функцию PHP parse_ini_file (), я получаю следующий вывод:Похоже, что "НЕТ" зарезервировано.Есть ли другой способ установить переменную с именем «NO»?

Ответы [ 6 ]

4 голосов
/ 26 мая 2011

Другим хаком было бы обратить ваши ini-ключи к их значениям и использовать array_flip :

<?php

$ini =
"
    [country]
    Sweden = 'SE'
    Norway = 'NO'
    Finland = 'FI'
";

$countries = parse_ini_string($ini, true);
$countries = array_flip($countries["country"]);
echo $countries["NO"];

Тем не менее, вам нужно будет использовать кавычки вокруг НЕТ (по крайней мере), если вы делаете

Norway = NO

вы не получите сообщение об ошибке, но значение для $ стран ["NO"] будет пустой строкой.

3 голосов
/ 02 июня 2015

Вероятно, это немного запоздало, но то, как работает PHP parse_ini_file, настолько обеспокоило меня, что я написал свой собственный маленький парсер.

Не стесняйтесь использовать его, но используйте с осторожностью, он только поверхностно протестирован!

// the exception used by the parser
class IniParserException extends \Exception {

    public function __construct($message, $code = 0, \Exception $previous = null) {
        parent::__construct($message, $code, $previous);
    }

    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

}

// the parser
function my_parse_ini_file($filename, $processSections = false) {
    $initext = file_get_contents($filename);
    $ret = [];
    $section = null;
    $lineNum = 0;
    $lines = explode("\n", str_replace("\r\n", "\n", $initext));
    foreach($lines as $line) {
        ++$lineNum;

        $line = trim(preg_replace('/[;#].*/', '', $line));
        if(strlen($line) === 0) {
            continue;
        }

        if($processSections && $line{0} === '[' && $line{strlen($line)-1} === ']') {
            // section header
            $section = trim(substr($line, 1, -1));
        } else {
            $eqIndex = strpos($line, '=');
            if($eqIndex !== false) {
                $key = trim(substr($line, 0, $eqIndex));
                $matches = [];
                preg_match('/(?<name>\w+)(?<index>\[\w*\])?/', $key, $matches);
                if(!array_key_exists('name', $matches)) {
                    throw new IniParserException("Variable name must not be empty! In file \"$filename\" in line $lineNum.");
                }
                $keyName = $matches['name'];
                if(array_key_exists('index', $matches)) {
                    $isArray = true;
                    $arrayIndex = trim($matches['index']);
                    if(strlen($arrayIndex) == 0) {
                        $arrayIndex = null;
                    }
                } else {
                    $isArray = false;
                    $arrayIndex = null;
                }

                $value = trim(substr($line, $eqIndex+1));
                if($value{0} === '"' && $value{strlen($value)-1} === '"') {
                    // too lazy to check for multiple closing " let's assume it's fine
                    $value = str_replace('\\"', '"', substr($value, 1, -1));
                } else {
                    // special value
                    switch(strtolower($value)) {
                        case 'yes':
                        case 'true':
                        case 'on':
                            $value = true;
                            break;
                        case 'no':
                        case 'false':
                        case 'off':
                            $value = false;
                            break;
                        case 'null':
                        case 'none':
                            $value = null;
                            break;
                        default:
                            if(is_numeric($value)) {
                                $value = $value + 0; // make it an int/float
                            } else {
                                throw new IniParserException("\"$value\" is not a valid value! In file \"$filename\" in line $lineNum.");
                            }
                    }
                }

                if($section !== null) {
                    if($isArray) {
                        if(!array_key_exists($keyName, $ret[$section])) {
                            $ret[$section][$keyName] = [];
                        }
                        if($arrayIndex === null) {
                            $ret[$section][$keyName][] = $value;
                        } else {
                            $ret[$section][$keyName][$arrayIndex] = $value;
                        }
                    } else {
                        $ret[$section][$keyName] = $value;
                    }
                } else {
                    if($isArray) {
                        if(!array_key_exists($keyName, $ret)) {
                            $ret[$keyName] = [];
                        }
                        if($arrayIndex === null) {
                            $ret[$keyName][] = $value;
                        } else {
                            $ret[$keyName][$arrayIndex] = $value;
                        }
                    } else {
                        $ret[$keyName] = $value;
                    }
                }
            }
        }
    }

    return $ret;
}

Чем это отличается? Имена переменных могут состоять только из буквенно-цифровых символов, но не имеют к ним никаких ограничений. Строки должны быть заключены в "все остальное должно быть специальным значением, таким как no, yes, true, false, on, off, null или none. Для отображения см. код.

2 голосов
/ 26 мая 2011

Вид взлома, но вы можете добавить обратные метки вокруг имен ключей:

[country]
`SE` = Sweden
`NO` = Norway
`FI` = Finland

Тогда получите к ним доступ так:

$result = parse_ini_file('test.ini');
echo "{$result['`NO`']}\n";

Выход:

$ php test.php
Norway
0 голосов
/ 25 июля 2016

Я столкнулся с той же проблемой и пытался избежать имени всеми возможными способами.

Потом я вспомнил, что из-за синтаксиса INI имена и значения будут обрезаны, поэтому следующий обходной путь МОЖЕТ сделать свое дело:

NL = Netherlands
; A whitespace before the name
 NO = Norway
PL = Poland

И это работает;) Пока ваши коллеги читают комментарии (что не всегда так) и не удаляют их случайно. Так что да, решение для переворачивания массива - безопасная ставка.

0 голосов
/ 08 июля 2014

Я получал эту ошибку, когда в строке были одинарные кавычки, такие как 't или'. Чтобы избавиться от проблемы, я обернул строку в двойные кавычки:

До:

You have selected 'Yes' but you haven't entered the date's flexibility

После того, как:

"You have selected 'Yes' but you haven't entered the date's flexibility"
0 голосов
/ 26 мая 2011

На странице руководства для parse_ini_file:

Есть зарезервированные слова, которые нельзя использовать в качестве ключей для ini-файлов.К ним относятся: null, да, нет, true, false, on, off, none.

Так что нет, вы не можете установить переменную NO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...