Подтвердить что ты не робот

PHP-массив с числовыми ключами как строка не может использоваться

У меня есть массив PHP, который имеет числовые ключи как строковый тип.

Но когда я пытаюсь получить к ним доступ, PHP дает мне ошибку индекса undefined.

$a = (array)json_decode('{"1":1,"2":2}');
var_dump($a);
var_dump(isset($a[1]));
var_dump(isset($a["1"]));
var_dump($a[1]);
var_dump($a["1"]);

Вывод:

array (size=2)
    '1' => int 1
    '2' => int 2

boolean false

boolean false

ERROR: E_NOTICE: Undefined offset: 1

null

ERROR: E_NOTICE: Undefined offset: 1

null

Как получить доступ к этим значениям?

Демо: http://codepad.viper-7.com/8O03IM

4b9b3361

Ответ 1

Итак, я не видел, чтобы другие ответы касались этого, но @xdazz приблизился.

Пусть начало нашей среды, $obj равно объектной нотации декодированной строки:

php > $obj = json_decode('{"1":1,"2":2}');

php > print_r($obj);
stdClass Object
(
    [1] => 1
    [2] => 2
)

php > var_dump( $obj );
object(stdClass)#1 (2) {
  ["1"]=>
  int(1)
  ["2"]=>
  int(2)
}

Если вы хотите получить доступ к строкам, мы знаем следующее:

php > echo $obj->1;

Parse error: parse error, expecting `T_STRING' or `T_VARIABLE' or `'{'' or `'$'' in php shell code on line 1

Доступ к объектным переменным

Вы можете получить к нему доступ так:

php > echo $obj->{1};
1

Это то же самое, что сказать:

php > echo $obj->{'1'};
1

Доступ к переменным массива

Проблема с массивами заключается в следующем: пустой пробел, что является проблемой при типизации.

php > echo $obj[1];
php >

Если вы возвращаете его обратно, объект снова доступен:

php > $obj = (object) $obj;
php > echo $obj->{1};
1

Вот функция, которая будет автоматизировать вышесказанное для вас:

function array_key($array, $key){
    $obj = (object) $array;
    return $obj->{$key};
}

Пример использования:

php > $obj = (array) $obj;
php > echo array_key($obj, 1);
1

php > echo array_key($obj, 2);
2

Ответ 2

Если вам нужен массив, установите второй параметр json_decode в true.

$a = json_decode('{"1":1,"2":2}', true);

Edit: когда вы бросаете объект std в массив, числовой строковый ключ не присваивается числу. Вот пример.

$obj = new stdClass;
$obj->{'1'} = 1;
$arr = (array) $obj;
var_dump($arr);
var_dump(isset($arr[1]));

Ответ 3

По-видимому, это известная проблема, и не планируется ее исправление; см. Doc Bug # 45959 Преобразование объекта в массив приводит к странному поведению:

Фиксация, которая подразумевает уменьшение производительности, следовательно, лучше кажется, что она остается известной проблемой, но документирована.

Эта победа (тогда) отмечена в документации для типа массива (выделение мое):

Если объект преобразуется в массив, результатом является массив, элементами которого являются свойства объекта. Ключи - это имена переменных-членов с несколькими заметными исключениями: целочисленные свойства недоступны.... Это может привести к неожиданному поведению....

Ответ 4

Да. Я согласен, PHP имеет проблемы с typecasting от объекта к массиву, но foreach обрабатывает разумно объект или ассоциативный массив.

$a = json_decode('{"1":1,"2":2}'); //need not typecast but doesnt break even if u typecast

foreach ($a as $k=>$v){
    echo $v;
}

Ответ 5

Я недавно встретил ту же проблему.

$obj = new stdClass();
$obj->{'0'} = "test";

$array = (array)$obj;
foreach ($array as $key => $value) {
   $array[$key] = strtoupper($value);
}
var_dump($array);

Этот код выводит:

array(2) {
  ["0"]=>
  string(4) "test"
  [0]=>
  string(4) "TEST"
}

Обнаружено, что при отладке метода для преобразования рекурсивных объектов в массив я был сумасшедшим.

Ответ 6

У меня была та же проблема (но с array_intersect_key).

Вот мое решение:

$array = array_combine(array_keys($array), $array);