Convertir un objet PHP en un tableau associatif

761

J'intègre une API à mon site Web qui fonctionne avec des données stockées dans des objets pendant que mon code est écrit à l'aide de tableaux.

J'aimerais une fonction rapide et sale pour convertir un objet en un tableau.

Haroldo
la source

Réponses:

1393

Il suffit de le transcrire

$array = (array) $yourObject;

Depuis les tableaux :

Si un objet est converti en tableau, le résultat est un tableau dont les éléments sont les propriétés de l'objet. Les clés sont les noms des variables membres, à quelques exceptions notables près: les propriétés entières sont inaccessibles; les variables privées ont le nom de classe ajouté au nom de la variable; les variables protégées ont un '*' ajouté au nom de la variable. Ces valeurs ajoutées ont des octets nuls de chaque côté.

Exemple: objet simple

$object = new StdClass;
$object->foo = 1;
$object->bar = 2;

var_dump( (array) $object );

Production:

array(2) {
  'foo' => int(1)
  'bar' => int(2)
}

Exemple: objet complexe

class Foo
{
    private $foo;
    protected $bar;
    public $baz;

    public function __construct()
    {
        $this->foo = 1;
        $this->bar = 2;
        $this->baz = new StdClass;
    }
}

var_dump( (array) new Foo );

Sortie (avec \ 0s édité pour plus de clarté):

array(3) {
  '\0Foo\0foo' => int(1)
  '\0*\0bar' => int(2)
  'baz' => class stdClass#2 (0) {}
}

Sortie avec var_exportau lieu de var_dump:

array (
  '' . "\0" . 'Foo' . "\0" . 'foo' => 1,
  '' . "\0" . '*' . "\0" . 'bar' => 2,
  'baz' =>
  stdClass::__set_state(array(
  )),
)

Le transtypage de cette manière ne fera pas de transtypage en profondeur du graphique d'objet et vous devez appliquer les octets nuls (comme expliqué dans le devis manuel) pour accéder à tous les attributs non publics. Cela fonctionne donc mieux lors de la conversion d'objets StdClass ou d'objets avec uniquement des propriétés publiques. Pour rapide et sale (ce que vous avez demandé) c'est bien.

Consultez également cet article de blog détaillé:

Gordon
la source
3
Pensez également à l' ArrayAccessinterface, peut-être en combinaison avec cette solution. php.net/manual/en/class.arrayaccess.php
alttag
3
Si vous avez des clés entières, elles seront converties en chaîne et cela peut provoquer un gros problème. Par exemple, [1 => "one"]devient["1" => "one"]
Oleg
2
@Howie Typecasting avec (array)et (object)fonctionne de manière fiable et identique sur toutes les versions depuis PHP 4.3. Voir 3v4l.org/X6lhm . Si vous obtenez une erreur de syntaxe, vous avez fait quelque chose de mal.
Gordon
2
@Howie voir la section Changelog pourempty . Vous ne pouvez pas utiliser une expression emptyantérieure à 5.5. Cela n'a rien à voir avec le transtypage;)
Gordon
4
Typecast. Oui. Tapez Freakin CAST! Bien. +1
Kaushik Makwana
346

Vous pouvez rapidement convertir des objets profondément imbriqués en tableaux associatifs en s'appuyant sur le comportement des fonctions d'encodage / décodage JSON:

$array = json_decode(json_encode($nested_object), true);
Jeff Standen
la source
12
C'est la meilleure solution si vous voulez une conversion récursive en profondeur (et bien sûr, ne vous occupez pas des mauvaises performances)
Julian Habekost
2
cela m'a totalement aidé avec ma situation, merci beaucoup.
Cesar Bielich
9
Respectueusement, je pense que cela fonctionne toujours ... n'oubliez pas de régler le 2e paramètre sur vrai.
Kirk B
3
Le deuxième paramètre a résolu le problème, fonctionnant pour PHP 5.6.25. Merci!
Ju Oliveira
3
Fonctionne parfaitement pour les objets imbriqués! Merci!
Melody
68

Du premier coup de Google pour " objet PHP à tableau d'assoc ", nous avons ceci:

function object_to_array($data)
{
    if (is_array($data) || is_object($data))
    {
        $result = array();
        foreach ($data as $key => $value)
        {
            $result[$key] = object_to_array($value);
        }
        return $result;
    }
    return $data;
}

La source est à codesnippets.joyent.com .

István Ujj-Mészáros
la source
16
Personnellement, je n'aime pas l'idée de rappeler la fonction pour chaque valeur. J'ai une version similaire, mais en 3 lignes: function objectToArray($o) { $a = array(); foreach ($o as $k => $v) $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v; return $a; }cela définit simplement tout ce qui n'est pas un objet ou un tableau et continue sans rappel répétitif de la méthode, sauf si cela est nécessaire.
SpYk3HH
13
@ SpYk3HH: écrivez votre propre réponse?
DanMan
2
Tout d' abord frappé pour « objet php tableau assoc » est stackoverflow.com/questions/4345554/...
Chris
Cela (et la version de @ SpYk3HH) semble fonctionner encore plus lentement que l'option json_encode ( stackoverflow.com/a/16111687/470749 ). Je ne sais pas pourquoi ces approches seraient préférables.
Ryan
1
@Ryan json encode and decode ne fonctionnera pas avec les valeurs NaN et INFINITE pour float et peut potentiellement avoir d'autres problèmes auxquels je ne peux pas penser du haut de ma tête, mais dans de nombreux cas, cela pourrait être une meilleure option. En ce qui concerne l' optimisation, ce dont il a besoin est le contexte - permettez - moi de brancher un poste que j'ai écrit à ce sujet evidentlycube.com/blog/game-optimization/when-to-optimize . le tl; dr étant, n'optimisez pas les choses qui ne prennent pas une grande partie du temps d'exécution car les avantages n'ont pas de sens dans le contexte de l'application entière.
Maurycy
61

Si vos propriétés d'objet sont publiques, vous pouvez:

$array =  (array) $object;

S'ils sont privés ou protégés, ils auront des noms de clés étranges sur la baie. Donc, dans ce cas, vous aurez besoin de la fonction suivante:

function dismount($object) {
    $reflectionClass = new ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        $array[$property->getName()] = $property->getValue($object);
        $property->setAccessible(false);
    }
    return $array;
}
Ramon K.
la source
Si votre propriété est protégée, setAccessible (false) la remettra-t-elle en visibilité protégée? ou le rendra-t-il privé?
Nick Mitchell
La seule solution que j'ai trouvée, qui fonctionnait avec des propriétés protégées. Merci
dav
3
meilleure solution pour les variables privées et protégées !!
HIRA THAKUR
Ici la ligne $ property-> setAccessible (false); sera exécuté sur chaque propriété - même si elle était publique ...
Francois Bourgeois
Excellent ... Incroyable ... Génial. Merci.
Farid Abbas
14
class Test{
    const A = 1;
    public $b = 'two';
    private $c = test::A;

    public function __toArray(){
        return call_user_func('get_object_vars', $this);
    }
}

$my_test = new Test();
var_dump((array)$my_test);
var_dump($my_test->__toArray());

Production

array(2) {
    ["b"]=>
    string(3) "two"
    ["Testc"]=>
    int(1)
}
array(1) {
    ["b"]=>
    string(3) "two"
}
Isius
la source
1
Avantages et inconvénients de cette solution? Qu'en est-il d'une classe déclarée comme classe Test {const A = 1; public $ parent = new Test (); }
Matteo Gaggiano
13

Voici du code:

function object_to_array($data) {
    if ((! is_array($data)) and (! is_object($data)))
        return 'xxx'; // $data;

    $result = array();

    $data = (array) $data;
    foreach ($data as $key => $value) {
        if (is_object($value))
            $value = (array) $value;
        if (is_array($value))
            $result[$key] = object_to_array($value);
        else
            $result[$key] = $value;
    }
    return $result;
}
Khalid
la source
fonctionne le mieux pour moi (mais je devais supprimer le 'xxx' et retourner les données $)
Gerfried
12

Toutes les autres réponses publiées ici ne fonctionnent qu'avec des attributs publics. Voici une solution qui fonctionne avec des objets de type JavaBeans en utilisant la réflexion et les getters:

function entity2array($entity, $recursionDepth = 2) {
    $result = array();
    $class = new ReflectionClass(get_class($entity));
    foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
        $methodName = $method->name;
        if (strpos($methodName, "get") === 0 && strlen($methodName) > 3) {
            $propertyName = lcfirst(substr($methodName, 3));
            $value = $method->invoke($entity);

            if (is_object($value)) {
                if ($recursionDepth > 0) {
                    $result[$propertyName] = $this->entity2array($value, $recursionDepth - 1);
                }
                else {
                    $result[$propertyName] = "***";  // Stop recursion
                }
            }
            else {
                $result[$propertyName] = $value;
            }
        }
    }
    return $result;
}
François Bourgeois
la source
Oui, mais ... si vous utilisez l'Object / Array en tant que variable, c'est ce que tout cela mène aussi, pourquoi avez-vous besoin d'autre chose que les publicpropriétés?
SpYk3HH
@ SpYk3HH: Je n'ai pas posé la question. Je ne sais même pas pourquoi quelqu'un préférerait un tableau à un objet en premier lieu.
Francois Bourgeois
Eh, je préfère souvent convertir les résultats de la requête en tableau juste pour fournir une "liste" uniforme pour la boucle, car la plupart des autres éléments d'une application qui doivent être "bouclés" ont tendance à être des tableaux. Simplifie l'écriture de "méthodes de boucle universelles". Souvent, si j'utilise un objet, je ne passe pas en revue ses propriétés, je l'utilise comme objet et j'utilise ces propriétés au besoin.
SpYk3HH
11

Qu'en est-il de get_object_vars($obj) ? Cela semble utile si vous ne souhaitez accéder qu'aux propriétés publiques d'un objet.

Voir get_object_vars .

Joe
la source
10

Tapez cast votre objet dans un tableau.

$arr =  (array) $Obj;

Cela résoudra votre problème.

Adeel
la source
5
Non, ce ne sera pas le cas si vous possédez des propriétés privées ou protégées.
forsberg
2
Solution la plus simple. Merci
ASD
6

Tout d'abord, si vous avez besoin d'un tableau à partir d'un objet, vous devez probablement constituer les données en tant que tableau en premier. Pensez-y.

N'utilisez pas de foreach instruction ou des transformations JSON. Si vous planifiez cela, vous travaillez à nouveau avec une structure de données, pas avec un objet.

Si vous en avez vraiment besoin, utilisez une approche orientée objet pour avoir un code propre et maintenable. Par exemple:

Objet en tant que tableau

class PersonArray implements \ArrayAccess, \IteratorAggregate
{
    public function __construct(Person $person) {
        $this->person = $person;
    }
    // ...
 }

Si vous avez besoin de toutes les propriétés, utilisez un objet de transfert:

class PersonTransferObject
{
    private $person;

    public function __construct(Person $person) {
        $this->person = $person;
    }

    public function toArray() {
        return [
            // 'name' => $this->person->getName();
        ];
    }

 }
John Smith
la source
6

Vous pouvez facilement utiliser cette fonction pour obtenir le résultat:

function objetToArray($adminBar){
    $reflector = new ReflectionObject($adminBar);
    $nodes = $reflector->getProperties();
    $out = [];
    foreach ($nodes as $node) {
        $nod = $reflector->getProperty($node->getName());
        $nod->setAccessible(true);
        $out[$node->getName()] = $nod->getValue($adminBar);
    }
    return $out;
}

Utilisez PHP 5 ou une version ultérieure.

Fiacre AYEDOUN
la source
5

Voici ma fonction PHP récursive pour convertir des objets PHP en un tableau associatif:

// ---------------------------------------------------------
// ----- object_to_array_recursive --- function (PHP) ------
// ---------------------------------------------------------
// --- arg1: -- $object  =  PHP Object         - required --
// --- arg2: -- $assoc   =  TRUE or FALSE      - optional --
// --- arg3: -- $empty   =  '' (Empty String)  - optional --
// ---------------------------------------------------------
// ----- Return: Array from Object --- (associative) -------
// ---------------------------------------------------------

function object_to_array_recursive($object, $assoc=TRUE, $empty='')
{
    $res_arr = array();

    if (!empty($object)) {

        $arrObj = is_object($object) ? get_object_vars($object) : $object;

        $i=0;
        foreach ($arrObj as $key => $val) {
            $akey = ($assoc !== FALSE) ? $key : $i;
            if (is_array($val) || is_object($val)) {
                $res_arr[$akey] = (empty($val)) ? $empty : object_to_array_recursive($val);
            }
            else {
                $res_arr[$akey] = (empty($val)) ? $empty : (string)$val;
            }
            $i++;
        }
    }
    return $res_arr;
}

// ---------------------------------------------------------
// ---------------------------------------------------------

Exemple d'utilisation:

// ---- Return associative array from object, ... use:
$new_arr1 = object_to_array_recursive($my_object);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, TRUE);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, 1);


// ---- Return numeric array from object, ... use:
$new_arr2 = object_to_array_recursive($my_object, FALSE);
rabatto
la source
3
.. ou oneliner:$new_arr1 = (array) $my_object;
FooBar
1
La version oneliner est peu profonde, donc pas équivalente.
Jonathan Lidbeck
5

Pour convertir un objet en tableau, convertissez-le simplement explicitement:

$name_of_array = (array) $name_of_object;
Shrish Shrivastava
la source
5

Vous pouvez également créer une fonction en PHP pour convertir un tableau d'objets:

function object_to_array($object) {
    return (array) $object;
}
Rakhi Prajapati
la source
@ Akintunde-Rotimi, j'ai créé une fonction commune et montré.
Rakhi Prajapati
4

Vous pouvez le faire lorsque vous obtenez des données en tant qu'objets à partir de bases de données:

// Suppose 'result' is the end product from some query $query

$result = $mysqli->query($query);
$result = db_result_to_array($result);

function db_result_to_array($result)
{
    $res_array = array();

    for ($count=0; $row = $result->fetch_assoc(); $count++)
        $res_array[$count] = $row;

    return $res_array;
}
metaldog
la source
2
Il y a une réponse acceptée avec 41 votes positifs, pas 1 ou 10, 41. Qu'est-ce que votre réponse y ajoute?
Yaroslav
4

Fonction personnalisée pour convertir stdClass en un tableau:

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

Une autre fonction personnalisée pour convertir Array en stdClass:

function arrayToObject($d) {
    if (is_array($d)) {
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return (object) array_map(__FUNCTION__, $d);
    } else {
        // Return object
        return $d;
    }
}

Exemple d'utilisation:

// Create new stdClass Object
$init = new stdClass;

// Add some test data
$init->foo = "Test data";
$init->bar = new stdClass;
$init->bar->baaz = "Testing";
$init->bar->fooz = new stdClass;
$init->bar->fooz->baz = "Testing again";
$init->foox = "Just test";

// Convert array to object and then object back to array
$array = objectToArray($init);
$object = arrayToObject($array);

// Print objects and array
print_r($init);
echo "\n";
print_r($array);
echo "\n";
print_r($object);
Bishoy
la source
4

Utilisation:

function readObject($object) {
    $name = get_class ($object);
    $name = str_replace('\\', "\\\\", $name); \\ Outcomment this line, if you don't use
                                              \\ class namespaces approach in your project
    $raw = (array)$object;

    $attributes = array();
    foreach ($raw as $attr => $val) {
        $attributes[preg_replace('('.$name.'|\*|)', '', $attr)] = $val;
    }
    return $attributes;
}

Il renvoie un tableau sans caractères spéciaux ni noms de classe.

ovnie
la source
4

Cette réponse n'est que l'union des différentes réponses de ce post, mais c'est la solution pour convertir un objet PHP avec des propriétés publiques ou privées avec des valeurs simples ou des tableaux en un tableau associatif ...

function object_to_array($obj)
{
    if (is_object($obj))
        $obj = (array)$this->dismount($obj);
    if (is_array($obj)) {
        $new = array();
        foreach ($obj as $key => $val) {
            $new[$key] = $this->object_to_array($val);
        }
    }
    else
        $new = $obj;
    return $new;
}

function dismount($object)
{
    $reflectionClass = new \ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        $array[$property->getName()] = $property->getValue($object);
        $property->setAccessible(false);
    }
    return $array;
}
Daniel Guerrero
la source
3

Quelques améliorations du code "bien connu"

/*** mixed Obj2Array(mixed Obj)***************************************/ 
static public function Obj2Array($_Obj) {
    if (is_object($_Obj))
        $_Obj = get_object_vars($_Obj);
    return(is_array($_Obj) ? array_map(__METHOD__, $_Obj) : $_Obj);   
} // BW_Conv::Obj2Array

Notez que si la fonction est membre d'une classe (comme ci-dessus), vous devez passer __FUNCTION__à__METHOD__

Gilbert BENABOU
la source
3

Vous pouvez également utiliser le composant Symfony Serializer

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$array = json_decode($serializer->serialize($object, 'json'), true);
Andrey Nilov
la source
3

Pour votre cas, c'était bien / beau si vous utilisiez les modèles "décorateur" ou "transformation du modèle de date". Par exemple:

Votre modèle

class Car {
    /** @var int */
    private $color;

    /** @var string */
    private $model;

    /** @var string */
    private $type;

    /**
     * @return int
     */
    public function getColor(): int
    {
        return $this->color;
    }

    /**
     * @param int $color
     * @return Car
     */
    public function setColor(int $color): Car
    {
        $this->color = $color;
        return $this;
    }

    /**
     * @return string
     */
    public function getModel(): string
    {
        return $this->model;
    }

    /**
     * @param string $model
     * @return Car
     */
    public function setModel(string $model): Car
    {
        $this->model = $model;

        return $this;
    }

    /**
     * @return string
     */
    public function getType(): string
    {
        return $this->type;
    }

    /**
     * @param string $type
     * @return Car
     */
    public function setType(string $type): Car
    {
        $this->type = $type;

        return $this;
    }
}

Décorateur

class CarArrayDecorator
{
    /** @var Car */
    private $car;

    /**
     * CarArrayDecorator constructor.
     * @param Car $car
     */
    public function __construct(Car $car)
    {
        $this->car = $car;
    }

    /**
     * @return array
     */
    public function getArray(): array
    {
        return [
            'color' => $this->car->getColor(),
            'type' => $this->car->getType(),
            'model' => $this->car->getModel(),
        ];
    }
}

Usage

$car = new Car();
$car->setType('type#');
$car->setModel('model#1');
$car->setColor(255);

$carDecorator = new CarArrayDecorator($car);
$carResponseData = $carDecorator->getArray();

Ce sera donc un code plus beau et plus correct.

Daniel Abyan
la source
3

Conversion et suppression d'étoiles ennuyeuses:

$array = (array) $object;
foreach($array as $key => $val)
{
    $new_array[str_replace('*_', '', $key)] = $val;
}

Ce sera probablement moins cher que d'utiliser des réflexions.

Fedir RYKHTIK
la source
2

Solution courte de @ SpYk3HH

function objectToArray($o)
{
    $a = array();
    foreach ($o as $k => $v)
        $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v;

    return $a;
}
Bsienn
la source
2

Étant donné que beaucoup de gens trouvent cette question en raison de problèmes avec l'accès dynamique aux attributs d'un objet, je soulignerai simplement que vous pouvez le faire en PHP: $valueRow->{"valueName"}

Dans le contexte (sortie HTML supprimée pour plus de lisibilité):

$valueRows = json_decode("{...}"); // Rows of unordered values decoded from a JSON object

foreach ($valueRows as $valueRow) {

    foreach ($references as $reference) {

        if (isset($valueRow->{$reference->valueName})) {
            $tableHtml .= $valueRow->{$reference->valueName};
        }
        else {
            $tableHtml .= " ";
        }
    }
}
radiatedDogsInFukushima
la source
2

En utilisant le transtypage, vous pouvez résoudre votre problème. Ajoutez simplement les lignes suivantes à votre objet de retour:

$arrObj = array(yourReturnedObject);

Vous pouvez également y ajouter une nouvelle paire clé / valeur en utilisant:

$arrObj['key'] = value;
Naveen Gupta
la source
2

Je pense que c'est une bonne idée d'utiliser des traits pour stocker la logique de conversion objet-tableau. Un exemple simple:

trait ArrayAwareTrait
{
    /**
     * Return list of Entity's parameters
     * @return array
     */
    public function toArray()
    {
        $props = array_flip($this->getPropertiesList());
        return array_map(
            function ($item) {
                if ($item instanceof \DateTime) {
                    return $item->format(DATE_ATOM);
                }
                return $item;
            },
            array_filter(get_object_vars($this), function ($key) use ($props) {
                return array_key_exists($key, $props);
            }, ARRAY_FILTER_USE_KEY)
        );
    }


    /**
     * @return array
     */
    protected function getPropertiesList()
    {
        if (method_exists($this, '__sleep')) {
            return $this->__sleep();
        }
        if (defined('static::PROPERTIES')) {
            return static::PROPERTIES;
        }
        return [];
    }
}

class OrderResponse
{
    use ArrayAwareTrait;

    const PROP_ORDER_ID = 'orderId';
    const PROP_TITLE = 'title';
    const PROP_QUANTITY = 'quantity';
    const PROP_BUYER_USERNAME = 'buyerUsername';
    const PROP_COST_VALUE = 'costValue';
    const PROP_ADDRESS = 'address';

    private $orderId;
    private $title;
    private $quantity;
    private $buyerUsername;
    private $costValue;
    private $address;

    /**
     * @param $orderId
     * @param $title
     * @param $quantity
     * @param $buyerUsername
     * @param $costValue
     * @param $address
     */
    public function __construct(
        $orderId,
        $title,
        $quantity,
        $buyerUsername,
        $costValue,
        $address
    ) {
        $this->orderId = $orderId;
        $this->title = $title;
        $this->quantity = $quantity;
        $this->buyerUsername = $buyerUsername;
        $this->costValue = $costValue;
        $this->address = $address;
    }

    /**
     * @inheritDoc
     */
    public function __sleep()
    {
        return [
            static::PROP_ORDER_ID,
            static::PROP_TITLE,
            static::PROP_QUANTITY,
            static::PROP_BUYER_USERNAME,
            static::PROP_COST_VALUE,
            static::PROP_ADDRESS,
        ];
    }

    /**
     * @return mixed
     */
    public function getOrderId()
    {
        return $this->orderId;
    }

    /**
     * @return mixed
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @return mixed
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * @return mixed
     */
    public function getBuyerUsername()
    {
        return $this->buyerUsername;
    }

    /**
     * @return mixed
     */
    public function getCostValue()
    {
        return $this->costValue;
    }

    /**
     * @return string
     */
    public function getAddress()
    {
        return $this->address;
    }
}

$orderResponse = new OrderResponse(...);
var_dump($orderResponse->toArray());
Vitaly Pugach
la source
1
$Menu = new Admin_Model_DbTable_Menu(); 
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu(); 
$Addmenu->populate($row->toArray());
Saurabh Chandra Patel
la source
Je suppose que cette réponse est pour un dossier Doctrine (ou similaire).
nikoskip du
1

Ici, j'ai créé une méthode objectToArray () , qui fonctionne également avec des objets récursifs, comme lorsque $objectAcontient $objectBqui pointe à nouveau vers$objectA .

De plus, j'ai limité la sortie aux propriétés publiques à l'aide de ReflectionClass. Débarrassez-vous-en, si vous n'en avez pas besoin.

    /**
     * Converts given object to array, recursively.
     * Just outputs public properties.
     *
     * @param object|array $object
     * @return array|string
     */
    protected function objectToArray($object) {
        if (in_array($object, $this->usedObjects, TRUE)) {
            return '**recursive**';
        }
        if (is_array($object) || is_object($object)) {
            if (is_object($object)) {
                $this->usedObjects[] = $object;
            }
            $result = array();
            $reflectorClass = new \ReflectionClass(get_class($this));
            foreach ($object as $key => $value) {
                if ($reflectorClass->hasProperty($key) && $reflectorClass->getProperty($key)->isPublic()) {
                    $result[$key] = $this->objectToArray($value);
                }
            }
            return $result;
        }
        return $object;
    }

Pour identifier les objets déjà utilisés, j'utilise une propriété protégée dans cette classe (abstraite), nommée $this->usedObjects. Si un objet imbriqué récursif est trouvé, il sera remplacé par la chaîne **recursive**. Sinon, il échouerait à cause de la boucle infinie.

Armin
la source
$usedObjectsn'est pas initialisé au début, donc l'appeler plusieurs fois donnera des résultats incorrects dans les appels ultérieurs. De plus, vous ne le libérez pas à la fin, donc vos objets ne seront jamais supprimés de la mémoire.
HappyDog
1

Il y a ma proposition, si vous avez des objets dans des objets avec même des membres privés:

public function dismount($object) {
    $reflectionClass = new \ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        if (is_object($property->getValue($object))) {
            $array[$property->getName()] = $this->dismount($property->getValue($object));
        } else {
            $array[$property->getName()] = $property->getValue($object);
        }
        $property->setAccessible(false);
    }
    return $array;
}
Karol Gasienica
la source
1

J'utilise ceci (solution récursive nécessaire avec les clés appropriées):

    /**
     * This method returns the array corresponding to an object, including non public members.
     *
     * If the deep flag is true, is will operate recursively, otherwise (if false) just at the first level.
     *
     * @param object $obj
     * @param bool $deep = true
     * @return array
     * @throws \Exception
     */
    public static function objectToArray(object $obj, bool $deep = true)
    {
        $reflectionClass = new \ReflectionClass(get_class($obj));
        $array = [];
        foreach ($reflectionClass->getProperties() as $property) {
            $property->setAccessible(true);
            $val = $property->getValue($obj);
            if (true === $deep && is_object($val)) {
                $val = self::objectToArray($val);
            }
            $array[$property->getName()] = $val;
            $property->setAccessible(false);
        }
        return $array;
    }

Exemple d'utilisation, le code suivant:

class AA{
    public $bb = null;
    protected $one = 11;

}

class BB{
    protected $two = 22;
}


$a = new AA();
$b = new BB();
$a->bb = $b;

var_dump($a)

Imprime ceci:

array(2) {
  ["bb"] => array(1) {
    ["two"] => int(22)
  }
  ["one"] => int(11)
}
lingue
la source
Comment pouvons-nous mettre à niveau votre fonction pour prendre en charge des objets avec un tableau d'objets?
celsowm