Zaktualizowano dla PHP 7.2
PHP 7.2 wprowadziło zmianę behawioralną dotyczącą konwersji kluczy numerycznych w rzutowaniu obiektów i tablic , co naprawia tę konkretną niespójność i sprawia, że wszystkie poniższe przykłady zachowują się zgodnie z oczekiwaniami.
Jedna rzecz mniej, o którą należy się mylić!
Oryginalna odpowiedź (dotyczy wersji wcześniejszych niż 7.2.0)
PHP ma swój udział w ciemnych zaułkach, w których naprawdę nie chcesz się znaleźć. Właściwości obiektów o nazwach będących liczbami są jedną z nich ...
Czego ci nigdy nie powiedzieli
Fakt nr 1: Nie można łatwo uzyskać dostępu do właściwości o nazwach, które nie są prawidłowymi nazwami zmiennych
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo;
Fakt # 2: Możesz uzyskać dostęp do takich właściwości za pomocą składni nawiasów klamrowych
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'};
Fakt # 3: Ale nie, jeśli nazwa właściwości składa się z samych cyfr!
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'};
echo $o->{'123'};
Przykład na żywo .
Fakt # 4: No chyba, że obiekt nie pochodzi z tablicy.
$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123';
echo $o1->{'123'};
echo $o2->{'123'};
Przykład na żywo .
Całkiem intuicyjny, nie zgadzasz się?
Co możesz zrobić
Opcja nr 1: zrób to ręcznie
Najbardziej praktycznym podejściem jest po prostu rzutowanie interesującego Cię obiektu z powrotem do tablicy, która pozwoli ci uzyskać dostęp do właściwości:
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'};
echo $a['123'];
Niestety nie działa to rekurencyjnie. Więc w twoim przypadku musisz zrobić coś takiego:
$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0'];
Opcja nr 2: opcja jądrowa
Alternatywnym podejściem byłoby napisanie funkcji, która rekurencyjnie konwertuje obiekty na tablice:
function recursive_cast_to_array($o) {
$a = (array)$o;
foreach ($a as &$value) {
if (is_object($value)) {
$value = recursive_cast_to_array($value);
}
}
return $a;
}
$arr = recursive_cast_to_array($myVar);
$value = $arr['highlighting']['448364']['Data']['0'];
Nie jestem jednak przekonany, że jest to lepsza opcja pod każdym względem, ponieważ niepotrzebnie rzutuje na tablice wszystkie właściwości, którymi nie jesteś zainteresowany, a także te, którymi jesteś.
Opcja nr 3: grając mądrze
Alternatywą dla poprzedniej opcji jest użycie wbudowanych funkcji JSON:
$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];
Funkcje JSON z łatwością wykonują rekursywną konwersję na tablicę bez konieczności definiowania jakichkolwiek funkcji zewnętrznych. Jakkolwiek wygląda to pożądane, ma tę wadę "nuke", jak opcja # 2, a dodatkowo wadę polegającą na tym, że jeśli wewnątrz obiektu znajdują się jakieś łańcuchy, muszą one być zakodowane w UTF-8 (jest to wymagane json_encode
).