Wie kann ich auf Objekteigenschaften mit Namen wie Ganzzahlen oder ungültigen Eigenschaftsnamen zugreifen?

Lesezeit: 7 Minuten

Benutzeravatar von avinash shah
Avinash Schah

ich benutze json_decode()etwas wie:

$myVar = json_decode($data)

Was mir eine Ausgabe wie diese gibt:

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

Ich möchte auf den Zeichenfolgenwert im Schlüssel zugreifen [0]. Wenn ich versuche, so etwas zu tun:

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

Ich bekomme diesen Fehler:

Analysefehler: Syntaxfehler, unerwartetes T_DNUMBER

Die beiden Ziffern/Ganzzahlen scheinen das Problem zu sein.

Jons Benutzeravatar
Jon

Aktualisiert für PHP 7.2

Mit PHP 7.2 wurde eine Verhaltensänderung eingeführt Konvertieren von numerischen Tasten in Objekt- und Array-Castswodurch diese spezielle Inkonsistenz behoben wird und alle folgenden Beispiele sich wie erwartet verhalten.

Eine Sache weniger, über die man sich ärgern muss!


Ursprüngliche Antwort (gilt für Versionen vor 7.2.0)

PHP hat seinen Anteil an dunklen Gassen, die Sie haben Wirklich Ich möchte mich nicht darin wiederfinden. Objekteigenschaften mit Namen, die Zahlen sind, sind eine davon …

Was sie dir nie gesagt haben

Fakt Nr. 1: Sie können nicht einfach auf Eigenschaften mit Namen zugreifen, die keine zulässigen Variablennamen sind

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

Fakt Nr. 2: Du dürfen Greifen Sie auf solche Eigenschaften mit geschweifter Klammersyntax zu

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

Fakt Nr. 3: Aber nicht wenn der Eigenschaftsname nur aus Ziffern besteht!

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

Live-Beispiel.

Fakt Nr. 4: Nun, es sei denn, das Objekt stammt nicht von vornherein aus einem Array.

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

Live-Beispiel.

Ziemlich intuitiv, meinst du nicht?

Was du tun kannst

Option 1: Mach es manuell

Der praktischste Ansatz besteht darin, das Objekt, an dem Sie interessiert sind, einfach wieder in ein Array umzuwandeln, mit dem Sie auf die Eigenschaften zugreifen können:

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

Leider funktioniert dies nicht rekursiv. In Ihrem Fall müssten Sie also Folgendes tun:

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

Option Nr. 2: die nukleare Option

Ein alternativer Ansatz wäre, eine Funktion zu schreiben, die Objekte rekursiv in Arrays konvertiert:

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

Ich bin jedoch nicht davon überzeugt, dass dies eine bessere Option auf ganzer Linie ist, da es unnötig alle Eigenschaften, die Sie sind, in Arrays umwandelt nicht interessiert, sowie diejenigen, die Sie sind.

Option Nr. 3: Clever spielen

Eine Alternative zur vorherigen Option besteht darin, die integrierten JSON-Funktionen zu verwenden:

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

Die JSON-Funktionen führen hilfreicherweise eine rekursive Konvertierung in ein Array durch, ohne dass externe Funktionen definiert werden müssen. So wünschenswert dies auch aussieht, es hat den “Atom”-Nachteil von Option #2 und zusätzlich der Nachteil, dass, wenn es irgendwelche Zeichenfolgen in Ihrem Objekt gibt, diese Zeichenfolgen muss in UTF-8 codiert sein (dies ist eine Anforderung von json_encode).

  • Fakt Nr. 0: Das Casting von Arrays in Objekte sollte von vornherein keinen stinkenden Sinn ergeben. Fakt Nr. 1 bis Fakt Nr. 3: unnötig.

    – Schrittmacher

    13. März 2015 um 10:34 Uhr

  • @ Pacerier: Ich stimme zu, dass es etwas fragwürdig ist, aber es kann in manchen Situationen durchaus Sinn machen. Wie auch immer, da es ist dokumentiert im Handbuch so zu arbeiten, unsere persönliche Meinung spielt keine Rolle.

    – Jon

    14. April 2015 um 19:12 Uhr


  • Eine Alternative zu Option 3, die kein UTF-8 erfordert, wäre $o = unserialize('O:8:"StdClass"' . substr(serialize($a),1));

    – OscarJ

    2. März 2016 um 13:25 Uhr

  • Gute Antwort! Im Handbuch es ist angegeben Ein Array wird in ein Objekt mit Eigenschaften konvertiert, die durch Tasten benannt werden … mit Ausnahme von numerischen Tasten, auf die nicht zugegriffen werden kann _sofern nicht wiederholt_. Was ist mit sofern nicht iteriert? Gibt es eine andere Möglichkeit, wie man auf diese Nummern zugreifen könnte?

    – Adam

    9. Oktober 2017 um 9:46 Uhr


Benutzeravatar von Pebbl
Kiesel

Ich wollte Jons eloquenter Erklärung nur den Grund hinzufügen, warum dies fehlschlägt. Das liegt alles daran, dass PHP beim Erstellen eines Arrays Schlüssel in Ganzzahlen umwandelt – wenn es möglich ist – was Suchprobleme bei Arrays verursacht, die in Objekte umgewandelt wurden, einfach weil der numerische Schlüssel erhalten bleibt. Dies ist problematisch, da alle Eigenschaftszugriffsoptionen Zeichenfolgen erwarten oder in Zeichenfolgen konvertieren. Sie können dies bestätigen, indem Sie Folgendes tun:

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

Was würde ausgeben:

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

Das Objekt hat also zwei Eigenschaftsschlüssel, einen numerischen (auf den nicht zugegriffen werden kann) und einen Zeichenfolgen-basierten. Das ist der Grund, warum Jon’s #Fact 4 funktioniert, denn wenn Sie die Eigenschaft mit geschweiften Klammern festlegen, definieren Sie immer einen zeichenfolgenbasierten Schlüssel und keinen numerischen.

Wenn Sie Jons Lösung verwenden, sie aber auf den Kopf stellen, können Sie ein Objekt aus Ihrem Array generieren, das immer Zeichenfolgen-basierte Schlüssel enthält, indem Sie Folgendes tun:

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

Von nun an können Sie eine der folgenden Methoden verwenden, da der Zugriff auf diese Weise immer den Wert innerhalb der geschweiften Klammern in einen String umwandelt:

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

Gutes altes unlogisches PHP…

Benutzeravatar von umesh kadam
umesh kadam

Für PHP7

Zugriff auf Objekteigenschaften mit Zahlen als Eigenschaftsnamen.

Es wird meistens benötigt, nachdem ein Array in ein Objekt umgewandelt wurde.

    $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

Benutzeravatar von Bluekable
Bluekable

Eine letzte Alternative zu Jons umfassender Antwort:

Einfach verwenden json_decode() mit dem zweiten Parametersatz auf WAHR.

$array = json_decode($url, true);

Dies gibt dann ein assoziatives Array anstelle eines Objekts zurück, sodass keine nachträgliche Konvertierung erforderlich ist.

Dies ist möglicherweise nicht für jede Anwendung geeignet, aber es hat mir wirklich geholfen, eine Eigenschaft des ursprünglichen Objekts einfach zu referenzieren.

Die Lösung wurde im Tutorial gefunden Umgang mit JSON wie ein Boss in PHP.

Benutzeravatar von Zydnar
Zydnar

Wenn ein Objekt mit beginnt @ wie:

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

Sie müssen verwenden:

print_r($parent_object->attributes());

Weil $parent_object->{'@attributes'} oder $parent_object['@attributes'] wird nicht funktionieren.

  • 3 Jahre später und das hilft immer noch Menschen, danke! Während Ihre Antwort mein Problem behebt, fehlt eine Erklärung. Kann jemand den Grund dafür erklären?

    – Schiedsrichter

    27. Dezember 2019 um 21:26 Uhr

Benutzeravatar von Nisse Engström
Nisse Engström

Diese Funktion hatte ich aus dem Netz kopiert. Wenn es wie angegeben funktioniert (“Funktion zum Konvertieren von stdClass-Objekten in mehrdimensionale Arrays”), versuchen Sie Folgendes:

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

?>
  • Übergeben Sie zuerst Ihr Array an objectToArray Funktion
  • nehmen Sie dann den Rückgabewert
  • Echo [highlighting][448364][Data][0]

Quelle: PHP stdClass zu Array und Array zu stdClass

  • 3 Jahre später und das hilft immer noch Menschen, danke! Während Ihre Antwort mein Problem behebt, fehlt eine Erklärung. Kann jemand den Grund dafür erklären?

    – Schiedsrichter

    27. Dezember 2019 um 21:26 Uhr

Benutzeravatar von Peter Mortensen
Peter Mortensen

Ich fürchte, Sie dürfen keine Objekte benennen, die mit Zahlen beginnen. Benennen Sie die erste in „448364“ um, beginnend mit einem Buchstaben.

Das zweite ist ein Array, und auf diese muss mit Klammern wie folgt zugegriffen werden:

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

stattdessen

  • Ich kann es nicht ändern. Die Ausgabe wird von einer Anwendung zurückgegeben, über die ich keine Kontrolle habe.

    – Avinash Schah

    26. April 2012 um 12:12 Uhr

1449410cookie-checkWie kann ich auf Objekteigenschaften mit Namen wie Ganzzahlen oder ungültigen Eigenschaftsnamen zugreifen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy