web-dev-qa-db-fra.com

Comment accéder aux propriétés d'objet avec des noms comme des entiers?

Comment accéder à une propriété PHP) dont le résultat est:

[highlighting] => stdClass Object
        (
            [448364] => stdClass Object
                (
                    [Data] => Array
                        (
                            [0] => Tax amount liability is ....... 

Je veux accéder à la valeur de chaîne dans la clé [0]. Je veux faire quelque chose comme:

print myVar->highlighting->448364->Data->0

Mais les deux chiffres/nombres entiers semblent poser problème.

MODIFIER:

Je vais donner un peu d’histoire ici pour savoir où puis-je obtenir maVar. J'utilise json_decode() quelque chose comme:

$myVar = json_decode(url)
84
avinash shah

Mis à jour pour PHP 7.2

PHP 7.2 a introduit un changement de comportement en conversion des clés numériques en objets et tableaux , qui corrige cette incohérence particulière et fait en sorte que tous les exemples suivants se comportent comme prévu.

Une chose de moins à confondre!


Réponse originale (s'applique aux versions antérieures à 7.2.0)

PHP a sa part de ruelles sombres dans lesquelles vous vraiment ne voulez pas vous retrouver à l'intérieur. Les propriétés d'objet avec des noms qui sont des nombres est l'un d'eux ...

Qu'est-ce qu'ils ne vous ont jamais dit

Fait n ° 1: Vous ne pouvez pas accéder facilement à des propriétés avec des noms qui ne sont pas des noms de variables légaux

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // error

Fait n ° 2: Vous pouvez accéder à ces propriétés avec la syntaxe entre accolades

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!

Fait n ° 3: Mais pas si le nom de la propriété est composé uniquement de chiffres!

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
echo $o->{'123'}; // error!

Exemple en direct .

Fait n ° 4: Bien, à moins que l'objet ne vienne pas d'un tableau.

$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?

Exemple en direct .

Assez intuitif, vous n'êtes pas d'accord?

Ce que tu peux faire

Option n ° 1: faites-le manuellement

L’approche la plus pratique consiste simplement à reconvertir l’objet qui vous intéresse dans un tableau, ce qui vous permettra d’accéder aux propriétés:

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // error!
echo $a['123']; // OK!

Malheureusement, cela ne fonctionne pas de manière récursive. Donc, dans votre cas, vous devez faire quelque chose comme:

$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // at last!

Option n ° 2: l'option nucléaire

Une autre approche consisterait à écrire une fonction qui convertit les objets en tableaux de manière récursive:

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'];

Cependant, je ne suis pas convaincu qu'il s'agisse d'une meilleure option dans tous les domaines, car elle jettera inutilement dans un tableau toutes les propriétés qui vous intéressent pas, ainsi que celles qui vous intéressent.

Option n ° 3: jouer intelligemment

Une alternative à l'option précédente consiste à utiliser les fonctions JSON intégrées:

$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];

Les fonctions JSON effectuent utilement une conversion récursive en tableau sans qu'il soit nécessaire de définir des fonctions externes. Aussi désirable que cela puisse paraître, il présente l'inconvénient "nucléaire" de l'option n ° 2 et en plus l'inconvénient que s'il y a des chaînes dans votre objet, ces chaînes doivent = être codé en UTF-8 (il s’agit d’une exigence de json_encode ).

274
Jon

Je voulais juste ajouter à l'explication éloquente de Jon la raison pour laquelle cela échoue. C'est parce que lors de la création d'un tableau, php convertit les clés en entiers - si c'est le cas - ce qui pose des problèmes de recherche sur les tableaux qui ont été convertis en objets, tout simplement parce que la clé numérique est préservée. Cela est problématique car toutes les options d'accès aux propriétés attendent ou sont converties en chaînes. Vous pouvez le confirmer en procédant comme suit:

$arr = array('123' => 'abc');
$obj = (object) $arr;
$obj->{'123'} = 'abc';
print_r( $obj );

Ce qui donnerait:

stdClass Object ( 
  [123] => 'abc', 
  [123] => 'abc'
)

Donc, l'objet a deux clés de propriété, une numérique (qui est inaccessible) et une chaîne. C'est la raison pour laquelle Jon's #Fact 4 fonctionne, car la définition de la propriété à l'aide d'accolades signifie que vous définissez toujours une clé basée sur une chaîne plutôt que numérique.

En prenant la solution de Jon, mais en le retournant, vous pouvez générer un objet de votre tableau qui a toujours des clés basées sur des chaînes en procédant comme suit:

$obj = json_decode(json_encode($arr));

A partir de maintenant, vous pouvez utiliser l'un des éléments suivants, car un accès de cette manière convertit toujours la valeur à l'intérieur de l'accolade en une chaîne:

$obj->{123};
$obj->{'123'};

Bon vieux PHP illogique ...

10
Pebbl

Une dernière alternative à la réponse complète de Jon:

Utilisez simplement json_decode () avec le second paramètre défini sur true .

$array = json_decode($url, true);

Cela retourne ensuite un tableau associatif plutôt qu'un objet, il n'est donc pas nécessaire de convertir après coup.

Cela peut ne pas convenir à toutes les applications, mais cela m'a vraiment aidé à référencer facilement une propriété de l'objet oroginal.

La solution a été trouvée dans ce tutoriel - http://nitschinger.at/Handling-JSON-like-a-boss-in-PHP/

Cordialement

1
Bluekable

J'avais copié cette fonction du net. Si cela fonctionne comme il est dit ("Fonction pour convertir des objets stdClass en tableaux multidimensionnels"), essayez ce qui suit:

<?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;
        }
    }

?>
  • passez d'abord votre tableau à la fonction objectToArray
  • puis prenez la valeur de retour
  • écho [highlighting][448364][Data][0]

Source: PHP stdClass to Array et Array to stdClass

1
Ruwantha

Pour PHP 7

Accès aux propriétés d’objet numérotées comme nom de propriété. Généralement nécessaire après avoir moulé un tableau en objet.

    $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
0
umesh kadam

J'ai bien peur que vous n'ayez pas le droit de nommer des objets commençant par des nombres. Renommez le premier "448364" en commençant par une lettre.

Le second est un tableau, il faut y accéder par des crochets comme ceci:

print myVar->highlighting->test_448364->Data[0]

au lieu

0
Gustav

Si un objet commence par @ comme:

SimpleXMLElement Object (
    [@attributes] => Array (
        [href] => qwertyuiop.html
        [id] => html21
        [media-type] => application/xhtml+xml
    )
)

Vous devez utiliser:

print_r($parent_object->attributes());

car $parent_object->{'@attributes'} ou $parent_object['@attributes'] ne fonctionnera pas.

0
Zydnar