PHP – rekursives Array zu Objekt?

Lesezeit: 6 Minuten

Benutzer-Avatar
Peter

Gibt es eine Möglichkeit, eine mehrdimensionale zu konvertieren array zu einem stdClass Objekt in PHP?

Casting als (object) scheint nicht rekursiv zu funktionieren. json_decode(json_encode($array)) erzeugt das Ergebnis, das ich suche, aber es muss einen besseren Weg geben …

Benutzer-Avatar
Jakob Relk

Soweit ich das beurteilen kann, gibt es dafür keine vorgefertigte Lösung, sodass Sie einfach Ihre eigene erstellen können:

function array_to_object($array) {
   $obj = new stdClass();

   foreach ($array as $k => $v) {
      if (strlen($k)) {
         if (is_array($v)) {
            $obj->{$k} = array_to_object($v); //RECURSION
         } else {
            $obj->{$k} = $v;
         }
      }
   }
   
   return $obj;
}

  • Es ist möglich, dass PHP-Arrays leere Schlüssel haben, aber Objekte können keine leeren Eigenschaften haben. Es könnte sich lohnen, die zu wechseln else zu elseif ($k !== '')

    – Andy

    8. Mai 2013 um 16:07 Uhr

  • Vielen Dank, dass Sie bemerkt haben, dass dies nicht nur mit dem elseif möglich ist!

    – Andy

    10. Mai 2013 um 10:36 Uhr

  • Es scheint, als würde diese Funktion Werte mit Nullschlüsseln stillschweigend entfernen.

    – Bhavik Schah

    26. Juli 2016 um 10:55 Uhr

  • und was passiert mit den verschachtelten Arrays mit numerischen Tasten? Ich würde mich für die json-Kodierungs-/Dekodierungslösung entscheiden. Es ist vielleicht nicht optimal, aber am kugelsichersten.

    – itsjavi

    19. März 2017 um 23:29 Uhr

  • Die Methode json encode/decode konvertiert Nicht-StdClass-Objekte in StdClass-Objekte.

    – Tivie

    14. September 2017 um 14:26 Uhr

Ich weiß, dass diese Antwort spät kommt, aber ich werde sie für alle posten, die nach einer Lösung suchen.

Anstelle all dieser Schleifen usw. können Sie die native Funktion json_* von PHP verwenden. Ich habe ein paar praktische Funktionen, die ich oft benutze

/**
 * Convert an array into a stdClass()
 * 
 * @param   array   $array  The array we want to convert
 * 
 * @return  object
 */
function arrayToObject($array)
{
    // First we convert the array to a json string
    $json = json_encode($array);

    // The we convert the json string to a stdClass()
    $object = json_decode($json);

    return $object;
}


/**
 * Convert a object to an array
 * 
 * @param   object  $object The object we want to convert
 * 
 * @return  array
 */
function objectToArray($object)
{
    // First we convert the object into a json string
    $json = json_encode($object);

    // Then we convert the json string to an array
    $array = json_decode($json, true);

    return $array;
}

Hoffe, das kann hilfreich sein

  • Ich schätze den Post besser spät als nie, aber meine ursprüngliche Frage bezog sich auf diese Methode.

    – Petrus

    9. Februar 2012 um 6:01 Uhr

  • Ich habe keine gültige Verteidigung dafür, wie ich es geschafft habe, das zu übersehen :/ Ich kann nur meine Brille aufsetzen und Steve Erkle zitieren; Habe ich das getan!? Zurück zum Thema: Meines Wissens und meiner bescheidenen Meinung nach ist dies der sauberste und optimalste Weg, dies zu tun. Bitte korrigiere mich wenn ich falsch liege 🙂

    – Ole

    15. Februar 2012 um 19:18 Uhr


  • Es mag am saubersten sein, wenn Sie nach Codezeilen urteilen, aber es ist viel mehr Aufwand damit verbunden. Die Antwort von Jacob Relkin ist effizienter und genauso einfach zu codieren.

    – Petrus

    28. Februar 2012 um 0:29 Uhr

  • Dies funktioniert nur mit kompatiblen JSON-Datentypen. Wenn Sie Closures in Ihrem multidimensionalen Array speichern, wie ich es getan habe, wird dies nicht funktionieren.

    – Rafark

    20. Juni 2020 um 21:15 Uhr

Benutzer-Avatar
MAChitgarha

Sie und viele andere haben auf die integrierten JSON-Funktionen hingewiesen, json_decode() und json_encode(). Die Methode, die Sie erwähnt haben, funktioniert, aber nicht vollständig: Sie konvertiert keine indizierten Arrays in Objekte und sie bleiben als indizierte Arrays erhalten. Es gibt jedoch einen Trick, um dieses Problem zu umgehen. Sie können verwenden JSON_FORCE_OBJECT Konstante:

// Converts an array to an object recursively
$object = json_decode(json_encode($array, JSON_FORCE_OBJECT));

Tipp: Auch, wie erwähnt hierkönnen Sie ein Objekt mithilfe von JSON-Funktionen rekursiv in ein Array konvertieren:

// Converts an object to an array recursively
$array = json_decode(json_encode($object), true));    

Wichtiger Hinweis: Wenn Ihnen die Leistung wichtig ist, verwenden Sie diese Methode nicht. Es ist zwar kurz und sauber, aber es ist das langsamste unter den Alternativen. Siehe meine andere Antwort in diesem Thread zu diesem Thema.

Benutzer-Avatar
Priya

function toObject($array) {
    $obj = new stdClass();
    foreach ($array as $key => $val) {
        $obj->$key = is_array($val) ? toObject($val) : $val;
    }
    return $obj;
}

Du kannst den … benutzen array_map rekursiv:

public static function _arrayToObject($array) {
    return is_array($array) ? (object) array_map([__CLASS__, __METHOD__], $array) : $array;
}

Funktioniert perfekt für mich, da es zum Beispiel keine Carbon-Objekte in eine grundlegende stdClass umwandelt (was die json-Codierung/Decodierung tut).

  • Das ist einfach und süß und nützlich, wenn Sie diese Art von Hilfsprogramm innerhalb einer Klasse benötigen; Referenzen dazu sind schwer zu finden. Sie sollten es nur zur Verdeutlichung in eine Beispielklasse einschließen. Ansonsten gutes Beispiel für die KLASSE, METHODE Magie … man sieht es nicht oft.

    – ChrisN

    18. Januar 2018 um 13:52 Uhr


/**
 * Recursively converts associative arrays to stdClass while keeping integer keys subarrays as arrays
 * (lists of scalar values or collection of objects).
 */
function a2o( array $array ) {
    $resultObj = new \stdClass;
    $resultArr = array();
    $hasIntKeys = false;
    $hasStrKeys = false;
    foreach ( $array as $k => $v ) {
        if ( !$hasIntKeys ) {
            $hasIntKeys = is_int( $k );
        }
        if ( !$hasStrKeys ) {
            $hasStrKeys = is_string( $k );
        }
        if ( $hasIntKeys && $hasStrKeys ) {
            $e = new \Exception( 'Current level has both integer and string keys, thus it is impossible to keep array or convert to object' );
            $e->vars = array( 'level' => $array );
            throw $e;
        }
        if ( $hasStrKeys ) {
            $resultObj->{$k} = is_array( $v ) ? a2o( $v ) : $v;
        } else {
            $resultArr[$k] = is_array( $v ) ? a2o( $v ) : $v;
        }
    }
    return ($hasStrKeys) ? $resultObj : $resultArr;
} 

  • Das ist einfach und süß und nützlich, wenn Sie diese Art von Hilfsprogramm innerhalb einer Klasse benötigen; Referenzen dazu sind schwer zu finden. Sie sollten es nur zur Verdeutlichung in eine Beispielklasse einschließen. Ansonsten gutes Beispiel für die KLASSE, METHODE Magie … man sieht es nicht oft.

    – ChrisN

    18. Januar 2018 um 13:52 Uhr


Benutzer-Avatar
Tobi

Einige der anderen hier geposteten Lösungen können sequentielle Arrays nicht auseinanderhalten (was wäre [] in JS) aus Karten ({} in JS.) Für viele Anwendungsfälle ist es wichtig, PHP-Arrays, die alle fortlaufende numerische Schlüssel haben, die so belassen werden sollten, von PHP-Arrays zu unterscheiden, die keine numerischen Schlüssel haben, die in Objekte umgewandelt werden sollten. (Meine Lösungen unten sind für Arrays, die nicht in die beiden oben genannten Kategorien fallen, nicht definiert.)

Das json_decode(json_encode($x)) -Methode behandelt die beiden Typen korrekt, ist aber nicht die schnellste Lösung. Insgesamt ist es aber immer noch anständig 25µs pro Lauf mit meinen Beispieldaten (gemittelt über 1 Mio. Läufe, abzüglich des Loop-Overheads.)

Ich habe ein paar Variationen des rekursiven Konverters getestet und bin zu folgendem Ergebnis gekommen. Es erstellt alle Arrays und Objekte neu (durch Ausführen einer tiefen Kopie), scheint jedoch schneller zu sein als alternative Lösungen, die die vorhandenen Arrays ändern. Es schlägt um 11µs pro Ausführung meiner Beispieldaten:

function array_to_object($x) {
    if (!is_array($x)) {
        return $x;
    } elseif (is_numeric(key($x))) {
        return array_map(__FUNCTION__, $x);
    } else {
        return (object) array_map(__FUNCTION__, $x);
    }
}

Hier ist eine In-Place-Version. Bei einigen großen Eingabedaten, bei denen nur kleine Teile konvertiert werden müssen, kann es schneller sein, aber bei meinen Beispieldaten hat es gedauert 15µs pro Ausführung:

function array_to_object_inplace(&$x) {
    if (!is_array($x)) {
        return;
    }
    array_walk($x, __FUNCTION__);
    reset($x);
    if (!is_numeric(key($x))) {
        $x = (object) $x;
    }
}

Lösungen mit habe ich nicht ausprobiert array_walk_recursive()

  • Die erste Methode hat gerade ein leeres Objekt erstellt. Die zweite Methode hat es für mich nur geschafft, das äußerste assoziative Array in ein zu verwandeln stdClass Objekt. Alles andere blieb intern ein Array.

    – Der unbekannte Entwickler

    9. Februar 2018 um 2:18 Uhr


  • @KimberlyW Ich habe gerade beide getestet und sie funktionieren immer noch in PHP 7. Siehe dieses Beispiel

    – Tobi

    9. Februar 2018 um 10:13 Uhr

1311010cookie-checkPHP – rekursives Array zu Objekt?

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

Privacy policy