2012-06-18 19 views
25

Mam tablicę i PHP, a kiedy ją wydrukuję, widzę wartości, których potrzebuję, aby uzyskać dostęp, ale kiedy próbuję uzyskać do nich dostęp za pomocą ich klucza, otrzymuję komunikat PHP. I drukowane tablicę z print_r:Niezdefiniowane przesunięcie podczas uzyskiwania dostępu do elementu tablicy, który istnieje

Array 
(
    [207] => sdf 
    [210] => sdf 
) 

Przy próbie uzyskania dostępu do tablicy za pomocą indeksu dostaję nieokreślonej offsetu wypowiedzenia. Tu jest mój kodu:

print_r($output); 
echo $output[207]; // Undefined Offset 
echo $output["207"]; // Undefined Offset 

Tablica $output jest wynikiem wywołania array_diff_key i jest wprowadzany pierwotnie jako JSON za pośrednictwem żądania HTTP POST.

array_keys daje mi następujące:

Array 
(
    [0] => 207 
    [1] => 210 
) 

w odpowiedzi na komentarze:

var_dump(key($output)); Wyjścia:

string(3) "207" 

var_dump(isset($output[key($output)])); wyjścia:

bool(false) 
+1

Wypróbuj 'var_dump (key ($ output))' i powiedz nam, co otrzymujesz. – deceze

+0

Potrzebujesz więcej informacji. Jaki kontekst? Czy jest to skrypt po stronie serwera? –

+0

@deceze: Jest to wyjściowy ciąg '207' (długość = 3) ' –

Odpowiedz

1

Właśnie znaleziono this bug co powoduje elementy tablicy być niedostępne czasami w PHP, gdy tablica jest tworzona przez wywołanie unserialize.

Utwórz plik testowy PHP zawierającą (lub uruchamiane z linii poleceń) następujący skrypt:

<?php 

$a = unserialize('a:2:{s:2:"10";i:1;s:2:"01";i:2;}'); 

print $a['10']."\n"; 

$a['10'] = 3; 
$a['01'] = 4; 

print_r($a); 

foreach ($a as $k => $v) 
{ 
    print 'KEY: '; 
    var_dump($k); 
    print 'VAL: '; 
    var_dump($v); 
    print "\n"; 
} 

Jeśli wystąpią błędy masz wersję PHP z tego błędu w nim i polecam uaktualnienie do PHP 5.3

+0

Używam już 5.3.10. –

+0

Używam php 5.6 schowany w tym samym problemie – Linus

0

Jak wydrukowałeś tablicę? Proponuję print_r($arrayName);

Dalej, można wydrukować poszczególne elementy jak: echo $arrayName[0];

+0

Jak widać, użyłem 'print_r'. Dostęp do niego przez [0] nie jest możliwy. –

1

Spróbuj

var_dump($output); 
foreach ($output as $key => val) { 
    var_dump($key); 
    var_dump($val); 
} 

aby dowiedzieć się więcej o tym, co się dzieje.

Co dokładnie linia/instrukcja rzuca ci ostrzeżenie?

24

Patrz tej sekcji dotyczącej przekształcania przedmiotu na matrycy w PHP Manual:

Klucze są nazwy zmiennych użytkownika, z kilkoma wyjątkami: właściwości całkowite są unaccessible; zmienne prywatne mają nazwę klasy poprzedzoną nazwą zmiennej; chronione zmienne mają "*" przedrostka nazwy zmiennej.

Podczas konwersji do tablicy z obiektu w PHP, klucze tablicy całkowitej są przechowywane wewnętrznie jako ciągi. Kiedy uzyskujesz dostęp do elementów tablicy w PHP lub normalnie używasz tablicy, klucze zawierające prawidłowe liczby całkowite będą automatycznie konwertowane na liczby całkowite. Liczba całkowita przechowywana wewnętrznie jako ciąg jest niedostępnym kluczem.

zauważyć różnicę:

$x = (array)json_decode('{"207":"test"}'); 
var_dump(key($x)); // string(3) "207" 

var_dump($x); 
// array(1) { 
// ["207"]=> 
// string(4) "test" 
// } 


$y['207'] = 'test'; 
var_dump(key($y)); // int(207) 

var_dump($y); 
// array(1) { 
// [207]=> 
// string(4) "test" 
// } 

print_r na obu tych tablic daje identyczną moc, ale z var_dump widać różnice.

Oto kod, który reprodukuje dokładną problemu:

$output = (array)json_decode('{"207":"sdf","210":"sdf"}'); 

print_r($output); 
echo $output[207]; 
echo $output["207"]; 

a prostym rozwiązaniem jest przekazać w true do json_decode dla opcjonalnego assoc argumentu, aby określić, że chcesz tablicy nie jest obiektem:

$output = json_decode('{"207":"sdf","210":"sdf"}', true); 

print_r($output); 
echo $output[207]; 
echo $output["207"]; 
+0

Oryginalna tablica jest dekodowana z JSON POST. Ale tablica, z którą mam problem, jest wynikiem wywołania array_diff_key. –

+0

@KevinRave Tak, ponieważ tablica wejściowa do wywołania ma taki sam problem. Spróbuj uzyskać dostęp do '$ arr [207]' w tablicy, którą przekazujesz jako pierwszy argument 'array_diff_key', a zobaczysz dokładnie ten sam problem. Musisz naprawić źródło problemu, który będzie od rzucania obiektu do tablicy w pewnym momencie używając czegoś takiego: '$ tablica = (tablica) $ obj;' – Paulpro

+0

Próbowałem zmienić oryginalną tablicę. Wypróbowałem jeszcze kilka innych rzeczy. Nic nie działało. W rezultacie otrzymałem klucz/wartość poprzez zapętlenie foreach. Ale wydaje się, że to błąd. :-) –

19

problem powstaje, gdy casting do array obiekt, który ma klucze tekstowe, które są ważne całkowitymi.

Jeśli masz ten obiekt:

object(stdClass)#1 (2) { 
    ["207"]=> 
    string(3) "sdf" 
    ["210"]=> 
    string(3) "sdf" 
} 

i rzucasz ją

$array = (array)$object 

dostać tę tablicę

array(2) { 
    ["207"]=> 
    string(3) "sdf" 
    ["210"]=> 
    string(3) "sdf" 
} 

który ma klucze, które można uzyskać tylko poprzez zapętlenie za ich pośrednictwem, ponieważ bezpośredni dostęp, taki jak $array["207"], zawsze będzie converted do $array[207], która nie istnieje.

Ponieważ otrzymujesz przedmiot jak ten powyżej z json_decode() stosowanego do łańcucha jak

$json = '{"207":"sdf", "210":"sdf"}' 

Najlepszym rozwiązaniem byłoby, aby uniknąć klawiszy numerycznych w pierwszej kolejności. Są one prawdopodobnie lepsza modelowane jako wartości numeryczne tablicy obiektów:

$json = '[{"numAttr":207, "strAttr":"sdf"}, {"numAttr":210, "strAttr":"sdf"}]' 

Struktura danych ma wiele zalet w porównaniu z obecnym drugim:

  1. lepiej odzwierciedla oryginalnych danych, a zbiór obiektów które mają właściwość numeryczną
  2. jest łatwo rozszerzalny z innymi właściwościami
  3. jest bardziej mobilny w różnych systemach (jak widać, aktualna struc dane jest przyczyną problemów w PHP, ale jeśli użytkownik powinien używać innego języka, może łatwo napotkać inne podobne problemy).

Jeśli potrzebna jest mapa obiektów obiektu →, można ją szybko uzyskać, np.Coś takiego:

function getNumAttr($obj) { return $obj->numAttr; } // for backward compatibility 
$arr = json_decode($json); // where $json = '[{"numAttr":... 
$map = array_combine(array_map('getNumAttr', $arr), $arr); 

Innym rozwiązaniem byłoby zrobić jako ASCII-wapienne zasugerował: siła json_decode() do wyjściowych tablic asocjacyjnych zamiast obiektów, ustawiając swój drugi parametr do true:

$map = json_decode($json, true); 

Dla twoje dane wejściowe to produkuje bezpośrednio

array(2) { 
    [207]=> 
    string(3) "sdf" 
    [210]=> 
    string(3) "sdf" 
} 

Zauważ, że klucze tablicy są teraz liczbami całkowitymi zamiast ciągów.

Uważam jednak, że zmiana struktury danych JSON jest znacznie czystszym rozwiązaniem, chociaż rozumiem, że może nie być to możliwe.

+0

To zabawne, że po pewnym czasie zostało przegłosowane, a następnie unieważnione. W przypadku znalezienia czegoś błędnego w mojej odpowiedzi, byłbym ciekawy, co to jest –

+0

lub czy było to brakujące linki do instrukcji? Teraz są tam ... –

0

Spróbuj użyć mojego podejścia:

class ObjectToArray { 
    public static function convert($object) { 
     if(!is_object($object) && !is_array($object)) { 
      return $object; 
     } 

     if(is_object($object)) { 
      $object = get_object_vars($object); 
     } 

     return array_map('ObjectToArray::convert', $object); 
    } 
} 

$aNewArray = ObjectToArray::convert($oYourObject); 
0

Wystarczy umieścić error_reporting (0); w twojej metodzie lub na początku pliku. To rozwiąże twój problem.

Powiązane problemy