Как получить доступ к свойствам объекта с такими именами, как целые числа?
Как получить доступ к элементу массива PHP Associative, вывод которого:
[highlighting] => stdClass Object
(
[448364] => stdClass Object
(
[Data] => Array
(
[0] => Tax amount liability is .......
Я хочу получить доступ к строковому значению в ключе [0]. Я хочу сделать что-то вроде:
print myVar->highlighting->448364->Data->0
Но две цифры / целые числа, кажется, проблема.
РЕДАКТИРОВАТЬ:
Я расскажу здесь немного истории о том, откуда я могу получить myVar. я использую json_decode()
что-то вроде:
$myVar = json_decode(url)
6 ответов
Обновлено для PHP 7.2
В PHP 7.2 было введено поведенческое изменение в преобразовании числовых ключей при приведении объектов и массивов, что устраняет эту конкретную несогласованность и приводит к тому, что все последующие примеры ведут себя как ожидалось.
Еще одна вещь, о которой следует смутиться!
Оригинальный ответ (относится к версиям, предшествующим 7.2.0)
PHP имеет свою долю темных переулков, которые вы действительно не хотите, чтобы оказаться внутри. Свойства объекта с именами, которые являются числами, является одним из них...
То, что они никогда не говорили тебе
Факт № 1: Вы не можете легко получить доступ к свойствам с именами, которые не являются легальными именами переменных
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // error
Факт № 2: Вы можете получить доступ к таким свойствам с помощью синтаксиса фигурных скобок
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
Факт № 3: Но не в том случае, если имя свойства состоит из цифр!
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
echo $o->{'123'}; // error!
Факт №4: Ну, если только объект не пришел из массива.
$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123'; // setting property is OK
echo $o1->{'123'}; // error!
echo $o2->{'123'}; // works... WTF?
Довольно интуитивно понятно, ты не согласен?
Что ты можешь сделать
Вариант № 1: сделать это вручную
Наиболее практичный подход - просто преобразовать интересующий вас объект обратно в массив, что позволит вам получить доступ к свойствам:
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // error!
echo $a['123']; // OK!
К сожалению, это не работает рекурсивно. Так что в вашем случае вам нужно сделать что-то вроде:
$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // at last!
Вариант № 2: ядерный вариант
Альтернативный подход заключается в написании функции, которая преобразует объекты в массивы рекурсивно:
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'];
Тем не менее, я не уверен, что это лучший вариант по всем направлениям, потому что он будет бесполезно приводить к массивам все свойства, которые вас не интересуют, а также те, которые вы есть.
Вариант № 3: играть умно
Альтернативой предыдущей опции является использование встроенных функций JSON:
$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];
Функции JSON помогают выполнять рекурсивное преобразование в массив без необходимости определять какие-либо внешние функции. Каким бы желательным это ни выглядело, у него есть "ядерный" недостаток варианта № 2 и, кроме того, недостаток в том, что если в вашем объекте есть какие-либо строки, эти строки должны быть закодированы в UTF-8 (это требование json_encode
).
Просто хотел добавить к красноречивому объяснению Джона причину, по которой это не удается. Это все потому, что при создании массива php преобразует ключи в целые числа, если это возможно, что вызывает проблемы с поиском в массивах, приведенных к объектам, просто потому, что числовой ключ сохраняется. Это проблематично, потому что все параметры доступа к свойствам ожидают или преобразуют в строки. Вы можете подтвердить это, выполнив следующие действия:
$arr = array('123' => 'abc');
$obj = (object) $arr;
$obj->{'123'} = 'abc';
print_r( $obj );
Что бы вывести:
stdClass Object (
[123] => 'abc',
[123] => 'abc'
)
Таким образом, объект имеет два ключа свойства, один числовой (к которому нет доступа) и один на основе строки. Это причина, по которой Джон #Fact 4
работает, потому что установка свойства с помощью фигурных скобок означает, что вы всегда определяете ключ на основе строки, а не числовой.
Принимая решение Джона, но поворачивая его с ног на голову, вы можете сгенерировать объект из вашего массива, который всегда имеет строковые ключи, выполнив следующие действия:
$obj = json_decode(json_encode($arr));
Отныне вы можете использовать любое из следующего, потому что доступ таким образом всегда преобразует значение внутри фигурной скобки в строку:
$obj->{123};
$obj->{'123'};
Старый добрый нелогичный PHP...
Для PHP 7
Доступ к свойствам объекта с номерами в качестве имени свойства. В основном требуется после преобразования массива в объект.
$arr = [2,3,7];
$o = (object) $arr;
$t = "1";
$t2 = 1;
$t3 = (1);
echo $o->{1}; // 3
echo $o->{'1'}; // 3
echo $o->$t; // 3
echo $o->$t2; // 3
echo $o->$t3; // 3
echo $o->1; // error
echo $o->(1); // error
Последняя альтернатива исчерпывающему ответу Джона:
Просто используйте json_decode() со вторым параметром, установленным в true.
$array = json_decode($url, true);
Затем он возвращает ассоциативный массив, а не объект, поэтому нет необходимости конвертировать по факту.
Это может не подходить для каждого приложения, но это действительно помогло мне легко ссылаться на свойство оригинального объекта.
Решение было найдено в этом руководстве - http://nitschinger.at/Handling-JSON-like-a-boss-in-PHP/
С уважением
Если объект начинается с @
лайк:
SimpleXMLElement Object (
[@attributes] => Array (
[href] => qwertyuiop.html
[id] => html21
[media-type] => application/xhtml+xml
)
)
Вы должны использовать:
print_r($parent_object->attributes());
так как $parent_object->{'@attributes'}
или же $parent_object['@attributes']
не сработает
Я скопировал эту функцию из сети. Если это работает как говорится ("Функция для преобразования объектов stdClass в многомерные массивы"), попробуйте следующее:
<?php
function objectToArray($d) {
if (is_object($d)) {
// Gets the properties of the given object
// with get_object_vars function
$d = get_object_vars($d);
}
if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return array_map(__FUNCTION__, $d);
}
else {
// Return array
return $d;
}
}
?>
- сначала передайте свой массив
objectToArray
функция - затем возьмите возвращаемое значение
- эхо
[highlighting][448364][Data][0]
Боюсь, вы не можете называть объекты, начиная с цифр. Переименуйте первый "448364", начиная с буквы.
Второй - это массив, доступ к которому осуществляется через скобки:
print myVar->highlighting->test_448364->Data[0]
вместо