2014-01-23 3 views
3

У меня есть массив. Вот это var_dump:Неопределенный индекс в массиве, но он есть

array(1) { 
    ["139"]=> 
    string(5) "my_data" 
} 

Мы видим, что у нас есть ключ 139, и это строка (вар отвалы ключ: строка (3) "139"). Я хочу, чтобы получить элемент из массива, вот код:

$bad_array = $this->get('some_data'); 

var_dump($bad_array); 
var_dump($my_key); 
var_dump(isset($bad_array[$my_key])); 
var_dump($bad_array[$my_key]); 

Вот вывод:

array(1) { 
    ["139"]=> 
    string(5) "my_data" 
} 
string(3) "139" // my key output 
bool(false) // it's not isset 
Notice: Undefined index: 139 in /my_file_path.php on line 89 
NULL 

ПОЧЕМУ ??? У меня есть строковая переменная, все ключи - это строки. Как это может быть?

+3

Это странно, что вы получите 'строку (5)' для '«my_data»' – Ryan

+2

Try 'var_dump (bin2hex ($ my_key), bin2hex (ключ ($ bad_array)))' и посмотреть, что вы получаете. – deceze

+1

Пожалуйста, разместите свой код, который строит массив. – Dai

ответ

3

Короткий ответ

Array типа литья из Objectdoesn't work with integer properties (as strings i.e. "139").

Длинный ответ

Пучок тестирования кода:

<pre> 
<?php 
    $arr = array("139" => "some_data", "test" => "other_data"); 

    $good = (object) $arr; 
    $good_arr = (array) $good; 

    $bad = json_decode(json_encode($arr)); 
    $bad_arr = (array)($bad); 

    var_dump ($arr); 
    foreach ($arr as $k => $v) 
    var_dump (gettype ($k)); // 139 is integer 

    var_dump ($good); 
    foreach ($good as $k => $v) 
    var_dump (gettype ($k)); // 139 is integer 

    var_dump ($good_arr); 
    foreach ($good_arr as $k => $v) 
    var_dump (gettype ($k)); // 139 is integer 

    var_dump ($bad); 
    foreach ($bad as $k => $v) 
    var_dump (gettype ($k)); // 139 is string 

    var_dump ($bad_arr); 
    foreach ($bad_arr as $k => $v) 
    var_dump (gettype ($k)); // 139 is string 

    var_dump ($arr[139]);   // string(9) "some_data" 
    var_dump ($arr["139"]);  // string(9) "some_data" 
    var_dump ($arr["test"]);  // string(10) "other_data" 

    var_dump ($good->{139});  // NULL 
    var_dump ($good->{"139"}); // NULL 
    var_dump ($good->{"test"}); // string(10) "other_data" 

    var_dump ($good_arr[139]); // string(9) "some_data" 
    var_dump ($good_arr["139"]); // string(9) "some_data" 
    var_dump ($good_arr["test"]); // string(10) "other_data" 

    var_dump ($bad->{139});  // string(9) "some_data" 
    var_dump ($bad->{"139"});  // string(9) "some_data" 
    var_dump ($bad->{"test"}); // string(10) "other_data" 

    var_dump ($bad_arr[139]);  // NULL 
    var_dump ($bad_arr["139"]); // NULL 
    var_dump ($bad_arr["test"]); // string(10) "other_data" 
?> 
</pre> 

bin2hex фактически показывает точно такое же значение, и foreach работает нормально.

Так как же возможно, что он не работает, когда мы пытаемся получить к нему доступ напрямую?
И как странно, что последнее показывает хорошо?

Ну, на самом деле, я получил ответ на второй вопрос от этого part from the doc talking about array type casting Как вы можете видеть, при преобразовании объекта в массив с отливкой типа, это не работает для числовых свойств, которые позволяют недоступны.

Для первого вопроса я предполагаю, что тип cast не изменяет способ представления данных в памяти, так что он все равно может перебирать его, как если бы это был объект.

Следующая лишь мои предположения о различиях между двумя сценариями:

В хорошем сценарии

PHP обрабатывает материал, все сам.Ключ массива типа string, представляющий integer, автоматически преобразуется в integer.
Тогда нет проблем, когда мы его конвертируем, оно становится собственностью (с integer) объекта $good, хотя оно недоступно (потому что оно пытается достичь свойства "139", а не 139). (NULL)
Когда мы произведем преобразование в массив $good_arr, структура данных не изменилась, и мы все еще можем получить к нему доступ, поскольку он достигает 139, а не "139".

В плохом сценарии

Здесь объект регенерируют json_decode. Эта функция не генерирует плохие объекты (и это хорошо!), Поэтому все свойства будут иметь тип string.
Вот почему мы можем получить доступ к собственности непосредственно от объекта здесь. Это действительное свойство (тип string), поэтому мы можем получить к нему доступ.
Но, как сказано в документах, когда мы возвращаем его обратно в array, структура данных не изменилась, поэтому мы не можем получить к ней доступ. Либо мы напишем $bad_arr[139], либо $bad_arr["139"] попытается получить доступ к значению с помощью ключа 139 (NULL), когда он действительно должен получить доступ к "139".

Заключение

Это типичный пример магии PHP «s. Преобразование string s в int автоматически в массивах является причиной вашей проблемы.

Так что ваше решение с использованием assoc параметров из json_decode, кажется, только один, который будет работать здесь:

json_decode($json_arr, true); 
2

У меня есть массив, затем я сохраняю его в redis. После сохранения я бросаю массив на объект через json_decode (json_encode ($ ar)).

$redis->save($array); 
$this->object = json_decode(json_encode($array)); 
... 

Тогда я бросаю в массиву снова:

$ar = (array)$this->obj; 

Если я это сделаю, я не могу получить доступ к свойствам массива. Решение:

$this->object = json_decode(json_encode($array), true); // get array 
... 
if (is_object($ar)) { 
    $ar = (array)$ar; 
} 

Странные вещи ...

+0

Удивительно, это точно - [Demo] (http://codepad.org/baqQKOM2) –

Смежные вопросы