Элемент массива доступа, индексированный с помощью числовой строки
Я столкнулся с чем-то странным.
У меня есть php-массив, индексированный цифровыми ключами.
Однако невозможно получить доступ к любому из элементов, потому что php автоматически обрабатывает числовые строки как целые числа, вызывая уведомление о недопустимом смещении.
В нормальных условиях его невозможно создать php-массив с числовыми индексами строк, но это может произойти с типом casting.
Воспроизведение:
$object = new stdClass();
$object->{'1'} = 'one';
$array = (array) $object;
var_dump($array);
/* produces
array(1) {
["1"]=>
string(3) "one"
}
*/
//none of the following will work
$key = '1';
echo $array[1], $array['1'], $array["1"], $array[(string)1], $array[$key];
Это просто ошибка в кромке? Я столкнулся с проблемой при попытке улучшить свой ответ для другого вопроса SO
Пример живого кода: http://codepad.viper-7.com/dFSlH1
Ответы
Ответ 1
Невероятно, но это нормальное поведение в php, оно считалось ошибкой (ссылка) в 2008 году.
Но они просто указали на manual для трансляции с (array)
:
Если объект преобразуется в массив, результатом является массив, Элементы - это свойства объекта. Ключами являются переменная-член имена с несколькими заметными исключениями: целочисленные свойства недоступна;
Вместо этого вы можете использовать get_object_vars():
$object = new stdClass();
$object->{'1'} = 'one';
$array = get_object_vars( $object );
$key = '1';
echo $array[1]."<br>";
echo $array['1']."<br>";
echo $array["1"]."<br>";
echo $array[(string)1]."<br>";
echo $array[$key]."<br>";
Не объясняет, почему это происходит, но является решением, чтобы избежать проблемы с литой.
Отключить тему, но я подумал, может быть, это интересно. Нашел это в manual.
Чтобы избежать таких проблем, всегда используйте целое число ИЛИ строку в качестве индекса, не смешивайте его и не используйте целые числа в строке.
Пример смешанного массива:
$array = array(
1 => "a",
"1" => "b",//overrides 1
1.5 => "c",//overrides "1"
true => "d",//overrides 1.5
);
var_dump($array);
Ответ 2
Вы можете использовать
$vars = get_object_vars($object);
echo $vars[1];
Ответ 3
Строковые ключи, содержащие допустимые целочисленные значения, будут автоматически сбрасываться в целые ключи в "нормальном" создании массива, но кажется, что отбрасывание из объекта в массив не применяется к той же логике.
Однако можно исправить, используя
$array = array_combine(array_keys($array), array_values($array));
после строки, которая создает массив из объекта. http://codepad.viper-7.com/v5rGJa
Хотя, как сказал Дэйв в своем комментарии, использование get_object_vars
выглядит как "более чистое" решение для меня.
Ответ 4
foreach ($array as $key => $value){
var_dump($key);
var_dump($value);
}
показывает
string(1) "1"
string(3) "one"
Но echo $array['"1"'];
дает
E_NOTICE : type 8 -- Undefined index: "1" -- at line 8
Это странно!