avinash shah
estoy usando json_decode()
algo como:
$myVar = json_decode($data)
Lo que me da una salida como esta:
[highlighting] => stdClass Object
(
[448364] => stdClass Object
(
[Data] => Array
(
[0] => Tax amount liability is .......
Quiero acceder al valor de la cadena en la clave. [0]. Cuando trato de hacer algo como:
print $myVar->highlighting->448364->Data->0;
me sale este error:
Error de análisis: error de sintaxis, T_DNUMBER inesperado
Los dos números/enteros allí parecen ser el problema.
Jon
Actualizado para PHP 7.2
PHP 7.2 introdujo un cambio de comportamiento en convertir claves numéricas en conversiones de objetos y matricesque soluciona esta particular inconsistencia y hace que todos los siguientes ejemplos se comporten como se esperaba.
¡Una cosa menos de qué confundirse!
Respuesta original (se aplica a versiones anteriores a la 7.2.0)
PHP tiene su parte de callejones oscuros que en realidad no quiero encontrarme dentro. Las propiedades de objetos con nombres que son números es una de ellas…
Lo que nunca te dijeron
Hecho #1: No puede acceder fácilmente a propiedades con nombres que no son nombres de variables legales
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // error
Hecho #2: Tú poder acceder a tales propiedades con la sintaxis de llaves
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
Hecho #3: Pero no si el nombre de la propiedad tiene todos los dígitos!
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
echo $o->{'123'}; // error!
Hecho #4: Bueno, a menos que el objeto no provenga de una matriz en primer lugar.
$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?
Bastante intuitivo, ¿no estás de acuerdo?
Lo que puedes hacer
Opción #1: hazlo manualmente
El enfoque más práctico es simplemente volver a convertir el objeto que le interesa en una matriz, lo que le permitirá acceder a las propiedades:
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // error!
echo $a['123']; // OK!
Desafortunadamente, esto no funciona recursivamente. Así que en tu caso tendrías que hacer algo como:
$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // at last!
Opción #2: la opción nuclear
Un enfoque alternativo sería escribir una función que convierta objetos en matrices recursivamente:
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'];
Sin embargo, no estoy convencido de que esta sea una mejor opción en todos los ámbitos porque convertirá innecesariamente en arreglos todas las propiedades que usted está no interesados, así como los que usted es.
Opción #3: jugar inteligentemente
Una alternativa a la opción anterior es usar las funciones JSON incorporadas:
$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];
Las funciones JSON realizan de manera útil una conversión recursiva a una matriz sin necesidad de definir ninguna función externa. Por muy deseable que parezca, tiene la desventaja “nuclear” de la opción n.º 2 y adicionalmente la desventaja de que si hay cadenas dentro de su objeto, esas cadenas debe estar codificado en UTF-8 (este es un requisito de json_encode
).
-
Hecho #0: La conversión de matrices en objetos no debería tener ningún sentido apestoso en primer lugar. Hecho #1 a Hecho #3: innecesario.
– Pacerier
13 de marzo de 2015 a las 10:34
-
@Pacerier: Estoy de acuerdo en que es algo cuestionable, pero puede tener sentido en algunas situaciones. De todos modos, ya que es documentado en el manual para trabajar así, nuestras opiniones personales realmente no importan.
– Jon
14/04/2015 a las 19:12
-
Una alternativa a la Opción n. ° 3 que no requiere UTF-8 sería
$o = unserialize('O:8:"StdClass"' . substr(serialize($a),1));
– OscarJ
2 de marzo de 2016 a las 13:25
-
¡Gran respuesta! En el manual se afirma Una matriz se convierte en un objeto con propiedades nombradas por claves… con la excepción de las teclas numéricas que serán inaccesibles _a menos que se repita_. con que es ment a menos que se repita? ¿Hay otra forma de acceder a estos números?
– Adán
9 de octubre de 2017 a las 9:46
Guijarro
Solo quería agregar a la elocuente explicación de Jon la razón por la cual esto falla. Todo se debe a que al crear una matriz, PHP convierte las claves en números enteros, si puede, lo que provoca problemas de búsqueda en las matrices que se han convertido en objetos, simplemente porque se conserva la clave numérica. Esto es problemático porque todas las opciones de acceso a la propiedad esperan o se convierten en cadenas. Puede confirmar esto haciendo lo siguiente:
$arr = array('123' => 'abc');
$obj = (object) $arr;
$obj->{'123'} = 'abc';
print_r( $obj );
Lo que daría salida:
stdClass Object (
[123] => 'abc',
[123] => 'abc'
)
Entonces, el objeto tiene dos claves de propiedad, una numérica (a la que no se puede acceder) y una basada en cadenas. Esta es la razón por la que Jon #Fact 4
funciona, porque al configurar la propiedad con llaves significa que siempre define una clave basada en cadenas, en lugar de numérica.
Tomando la solución de Jon, pero dándole la vuelta, puede generar un objeto de su matriz que siempre tenga claves basadas en cadenas haciendo lo siguiente:
$obj = json_decode(json_encode($arr));
De ahora en adelante, puede usar cualquiera de los siguientes porque el acceso de esta manera siempre convierte el valor dentro de la llave en una cadena:
$obj->{123};
$obj->{'123'};
Buen viejo PHP ilógico…
umesh kadam
Para PHP 7
Acceder a las propiedades del objeto que tienen números como nombre de propiedad.
Se necesita principalmente después de convertir una matriz en un objeto.
$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
Bluekable
Una alternativa final a la respuesta integral de Jon:
Simplemente use json_decodificar() con el segundo parámetro establecido en verdadero.
$array = json_decode($url, true);
Esto luego devuelve una matriz asociativa en lugar de un objeto, por lo que no hay necesidad de convertir después del hecho.
Puede que esto no sea adecuado para todas las aplicaciones, pero realmente me ayudó a hacer referencia fácilmente a una propiedad del objeto original.
La solución la encontré en el tutorial. Manejando JSON como un jefe en PHP.
Zydnar
Si un objeto comienza con @
como:
SimpleXMLElement Object (
[@attributes] => Array (
[href] => qwertyuiop.html
[id] => html21
[media-type] => application/xhtml+xml
)
)
Tienes que usar:
print_r($parent_object->attributes());
porque $parent_object->{'@attributes'}
o $parent_object['@attributes']
no funcionará
-
3 años después y esto sigue ayudando a la gente, ¡gracias! Si bien su respuesta soluciona mi problema, carece de una explicación. ¿Alguien puede explicar la razón detrás de esto?
– Árbitro
27 de diciembre de 2019 a las 21:26
Nisse Engström
Había copiado esta función de la red. Si funciona como dice (“Función para convertir objetos stdClass en matrices multidimensionales”), intente lo siguiente:
<?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;
}
}
?>
- primero pase su matriz a
objectToArray
función - luego tome el valor de retorno
- eco
[highlighting][448364][Data][0]
-
3 años después y esto sigue ayudando a la gente, ¡gracias! Si bien su respuesta soluciona mi problema, carece de una explicación. ¿Alguien puede explicar la razón detrás de esto?
– Árbitro
27 de diciembre de 2019 a las 21:26
Pedro Mortensen
Me temo que no está permitido nombrar objetos que comiencen con números. Cambie el nombre del primero a “448364” comenzando con una letra.
El segundo es una matriz, y se debe acceder a ellos mediante corchetes de la siguiente manera:
print myVar->highlighting->test_448364->Data[0]
en cambio
-
No puedo cambiarlo. La salida se devuelve desde una aplicación de la que no tengo control.
– avinash shah
26 de abril de 2012 a las 12:12