Convierta un objeto PHP en una matriz asociativa

761

Estoy integrando una API en mi sitio web que funciona con datos almacenados en objetos mientras mi código se escribe usando matrices.

Me gustaría una función rápida y sucia para convertir un objeto en una matriz.

Haroldo
fuente

Respuestas:

1393

Solo escríbelo

$array = (array) $yourObject;

De matrices :

Si un objeto se convierte en una matriz, el resultado es una matriz cuyos elementos son las propiedades del objeto. Las claves son los nombres de las variables miembro, con algunas excepciones notables: no se puede acceder a las propiedades enteras; las variables privadas tienen el nombre de la clase antepuesto al nombre de la variable; Las variables protegidas tienen un '*' antepuesto al nombre de la variable. Estos valores antepuestos tienen bytes nulos a cada lado.

Ejemplo: objeto simple

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

var_dump( (array) $object );

Salida:

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

Ejemplo: objeto complejo

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

Salida (con \ 0s editado para mayor claridad):

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

Salida con en var_exportlugar de var_dump:

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

La conversión de texto de esta manera no hará una conversión profunda del gráfico de objeto y debe aplicar los bytes nulos (como se explica en la cita manual) para acceder a los atributos no públicos. Entonces, esto funciona mejor cuando se convierten objetos StdClass u objetos con solo propiedades públicas. Para rápido y sucio (lo que pediste) está bien.

También vea esta publicación de blog en profundidad:

Gordon
fuente
3
Considere también la ArrayAccessinterfaz, quizás en combinación con esta solución. php.net/manual/en/class.arrayaccess.php
alttag
3
Si tiene teclas enteras, se convertirá en una cadena y esto puede causar un gran problema. Por ejemplo, [1 => "one"]se convierte en["1" => "one"]
Oleg
2
@Howie Typecasting con (array)y (object)funciona de manera confiable e igual en todas las versiones desde PHP 4.3. Ver 3v4l.org/X6lhm . Si obtiene un error de sintaxis, hizo algo mal.
Gordon
2
@Howie vea la secciónempty Registro de cambios para . No puede usar una expresión emptyanterior a 5.5. Esto no tiene ninguna relación con el encasillamiento;)
Gordon
44
Encasillar. Si. Escriba Freakin CAST! Bueno. +1
Kaushik Makwana
346

Puede convertir rápidamente objetos profundamente anidados en matrices asociativas confiando en el comportamiento de las funciones de codificación / decodificación JSON:

$array = json_decode(json_encode($nested_object), true);
Jeff Standen
fuente
12
Esta es la mejor solución si desea una conversión recursiva de profundidad completa (y, por supuesto, no le importa el mal rendimiento)
Julian Habekost
2
Esto me ayudó mucho con mi situación, muchas gracias.
Cesar Bielich
99
Respetuosamente, creo que todavía funciona ... no olvides establecer el segundo parámetro en verdadero.
Kirk B
3
El segundo parámetro resolvió el problema, trabajando para PHP 5.6.25. ¡Gracias!
Ju Oliveira
3
¡Funciona perfecto para objetos anidados! ¡Gracias!
Melodía
68

Desde el primer hit de Google para " Objeto PHP a matriz asociada " tenemos esto:

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 fuente está en codesnippets.joyent.com .

István Ujj-Mészáros
fuente
16
Personalmente, no me gusta la idea de recordar la función para cada valor. Tengo una versión similar, pero en 3 líneas: function objectToArray($o) { $a = array(); foreach ($o as $k => $v) $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v; return $a; }esto establece cualquier cosa que no sea un objeto o matriz y continúa sin una repetición del método, a menos que sea necesario.
SpYk3HH
13
@ SpYk3HH: escribe tu propia respuesta?
DanMan
2
El primer hit para "php object to assoc array" es stackoverflow.com/questions/4345554/…
Chris
Esto (y la versión de @ SpYk3HH) parece funcionar incluso más lento para mí que la opción json_encode ( stackoverflow.com/a/16111687/470749 ). No sé por qué estos enfoques serían preferibles.
Ryan
1
La codificación y decodificación de @Ryan json no funcionará con los valores NaN e INFINITE para flotante y, potencialmente, puede tener otros problemas que no puedo pensar desde la parte superior de mi cabeza, pero para muchos casos podría ser una mejor opción. En cuanto a la optimización, lo que necesita es contexto: permítanme conectar una publicación que escribí sobre este tema evidentementecube.com/blog/game-optimization/when-to-optimize . Por lo tanto, no optimice las cosas que no requieren gran parte del tiempo de ejecución porque los beneficios no tienen sentido en el contexto de toda la aplicación.
Maurycy
61

Si sus propiedades de objeto son públicas, puede hacer:

$array =  (array) $object;

Si son privados o están protegidos, tendrán nombres de claves extraños en la matriz. Entonces, en este caso necesitará la siguiente función:

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.
fuente
Si su propiedad está protegida, ¿setAccessible (false) la cambiará nuevamente a visibilidad protegida? o lo hará privado?
Nick Mitchell
La única solución que encontré, que funcionó con propiedades protegidas. Gracias
dav
3
¡La mejor solución para variables privadas y protegidas!
HIRA THAKUR
Aquí la línea $ property-> setAccessible (false); se ejecutará en todas las propiedades, incluso si era público ...
Francois Bourgeois
Excelente ... Increíble ... Impresionante. Gracias.
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());

Salida

array(2) {
    ["b"]=>
    string(3) "two"
    ["Testc"]=>
    int(1)
}
array(1) {
    ["b"]=>
    string(3) "two"
}
Isius
fuente
1
¿A favor y en contra de esta solución? ¿Qué pasa con una clase declarada como clase Test {const A = 1; public $ parent = new Test (); }
Matteo Gaggiano
13

Aquí hay un código:

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
fuente
funciona mejor para mí (pero necesitaba eliminar el 'xxx' y devolver $ datos)
Gerfried
12

Todas las demás respuestas publicadas aquí solo funcionan con atributos públicos. Aquí hay una solución que funciona con objetos similares a JavaBeans que usan reflexión y captadores:

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;
}
Francois Bourgeois
fuente
Sí, pero ... si está utilizando Object / Array como una variable, que es lo que todo esto conlleva también, ¿por qué necesita algo más que las publicpropiedades?
SpYk3HH
@ SpYk3HH: no hice la pregunta. Ni siquiera sé por qué alguien preferiría una matriz sobre un objeto en primer lugar.
Francois Bourgeois
Eh, a menudo prefiero convertir los resultados de la consulta en una matriz solo para proporcionar una "lista" uniforme para recorrer, ya que la mayoría de las otras cosas en una aplicación que deben "enlazarse" tienden a ser matrices. Simplemente hace que sea fácil escribir "métodos de bucle universal". A menudo, si estoy haciendo uso de un objeto, no estoy recorriendo sus propiedades, lo estoy usando como un objeto y uso esas propiedades según sea necesario.
SpYk3HH
11

Qué pasa get_object_vars($obj) ? Parece útil si solo desea acceder a las propiedades públicas de un objeto.

Ver get_object_vars .

Joe
fuente
10

Escriba emitir su objeto a una matriz.

$arr =  (array) $Obj;

Resolverá tu problema.

Adeel
fuente
55
No, no lo hará, si tiene propiedades privadas o protegidas.
forsberg
2
La solución más simple. Gracias
ASD
6

En primer lugar, si necesita una matriz de un objeto, probablemente debería constituir los datos como una matriz primero. Piénsalo.

No uses un foreach declaración o transformaciones JSON. Si está planeando esto, nuevamente está trabajando con una estructura de datos, no con un objeto.

Si realmente lo necesita, utilice un enfoque orientado a objetos para tener un código limpio y fácil de mantener. Por ejemplo:

Objeto como matriz

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

Si necesita todas las propiedades, use un objeto de transferencia:

class PersonTransferObject
{
    private $person;

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

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

 }
John Smith
fuente
6

Puede usar fácilmente esta función para obtener el resultado:

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

Use PHP 5 o posterior.

Fiacre AYEDOUN
fuente
5

Aquí está mi función PHP recursiva para convertir objetos PHP en una matriz asociativa:

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

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

Ejemplo de uso:

// ---- 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
fuente
3
.. o el oneliner:$new_arr1 = (array) $my_object;
FooBar
1
La versión en línea es poco profunda, por lo que no es equivalente.
Jonathan Lidbeck
5

Para convertir un objeto en una matriz, simplemente expórtalo explícitamente:

$name_of_array = (array) $name_of_object;
Shrish Shrivastava
fuente
5

También puede crear una función en PHP para convertir una matriz de objetos:

function object_to_array($object) {
    return (array) $object;
}
Rakhi Prajapati
fuente
@ Akintunde-Rotimi, he creado una función común y lo mostré.
Rakhi Prajapati
4

Es posible que desee hacer esto cuando obtenga datos como objetos de bases de datos:

// 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
fuente
2
Hay una respuesta aceptada con 41 votos a favor, no 1 o 10, 41. ¿Qué le agrega su respuesta?
Yaroslav
4

Función personalizada para convertir stdClass en una matriz:

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

Otra función personalizada para convertir Array a 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;
    }
}

Ejemplo de uso:

// 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
fuente
4

Utilizar:

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

Devuelve una matriz sin caracteres especiales y nombres de clase.

ovnia
fuente
4

Esta respuesta es solo la unión de las diferentes respuestas de esta publicación, pero es la solución para convertir un objeto PHP con propiedades públicas o privadas con valores simples o matrices en una matriz asociativa ...

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
fuente
3

Algunas mejoras al código "bien conocido"

/*** 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

Tenga en cuenta que si la función es miembro de una clase (como arriba) debe cambiar __FUNCTION__a__METHOD__

Gilbert BENABOU
fuente
3

También puede usar el componente serializador de Symfony

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
fuente
3

Para su caso, era correcto / hermoso si usara los patrones de "decorador" o "transformación de modelo de fecha". Por ejemplo:

Su modelo

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

Decorador

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(),
        ];
    }
}

Uso

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

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

Entonces será un código más hermoso y más correcto.

Daniel Abyan
fuente
3

Convertir y eliminar estrellas molestas:

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

Probablemente, será más barato que usar reflejos.

Fedir RYKHTIK
fuente
2

Solución corta 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
fuente
2

Dado que muchas personas encuentran esta pregunta por tener problemas para acceder dinámicamente a los atributos de un objeto, solo señalaré que puede hacer esto en PHP: $valueRow->{"valueName"}

En contexto (salida HTML eliminada para facilitar la lectura):

$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
fuente
2

Al utilizar la conversión de texto puede resolver su problema. Simplemente agregue las siguientes líneas a su objeto de retorno:

$arrObj = array(yourReturnedObject);

También puede agregarle un nuevo par clave y valor utilizando:

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

Creo que es una buena idea usar rasgos para almacenar la lógica de conversión de objeto a matriz. Un simple ejemplo:

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
fuente
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
fuente
Supongo que esta respuesta es para un registro de Doctrina (o similar).
nikoskip
1

Aquí he creado un método objectToArray () , que también funciona con objetos recursivos, como cuando $objectAcontiene $objectBqué puntos nuevamente$objectA .

Además, he restringido la salida a propiedades públicas usando ReflectionClass. Deshágase de él, si no lo necesita.

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

Para identificar objetos ya usados, estoy usando una propiedad protegida en esta clase (abstracta), llamada $this->usedObjects. Si se encuentra un objeto anidado recursivo, será reemplazado por la cadena **recursive**. De lo contrario, fallaría debido al bucle infinito.

Armin
fuente
$usedObjectsno se inicializa al inicio, por lo que llamar esto varias veces dará resultados incorrectos en llamadas posteriores. Además, no lo liberas al final, por lo que tus objetos nunca se eliminarán de la memoria.
HappyDog
1

Ahí está mi propuesta, si tiene objetos en objetos con incluso miembros privados:

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
fuente
1

Utilizo esto (solución recursiva necesaria con las teclas adecuadas):

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

Ejemplo de uso, el siguiente código:

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)

Imprimirá esto:

array(2) {
  ["bb"] => array(1) {
    ["two"] => int(22)
  }
  ["one"] => int(11)
}
abadejo
fuente
¿Cómo podemos actualizar su función para admitir objetos con una matriz de objetos?
Celsowm