Converter um objeto PHP em uma matriz associativa

760

Estou integrando uma API ao meu site que funciona com dados armazenados em objetos enquanto meu código é escrito usando matrizes.

Eu gostaria de uma função rápida e suja para converter um objeto em uma matriz.

Haroldo
fonte

Respostas:

1392

Basta digitar

$array = (array) $yourObject;

Das matrizes :

Se um objeto é convertido em uma matriz, o resultado é uma matriz cujos elementos são as propriedades do objeto. As chaves são os nomes das variáveis ​​dos membros, com algumas exceções notáveis: propriedades inteiras são inacessíveis; variáveis ​​privadas têm o nome da classe anexado ao nome da variável; variáveis ​​protegidas têm um '*' anexado ao nome da variável. Esses valores anexados têm bytes nulos em ambos os lados.

Exemplo: Objeto Simples

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

var_dump( (array) $object );

Resultado:

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

Exemplo: Objeto complexo

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

Saída (com \ 0s editado para maior clareza):

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

Saída com em var_exportvez de var_dump:

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

A conversão de tipos dessa maneira não fará a conversão profunda do gráfico do objeto e você precisará aplicar os bytes nulos (conforme explicado na cotação manual) para acessar quaisquer atributos não públicos. Portanto, isso funciona melhor ao converter objetos StdClass ou objetos com apenas propriedades públicas. Para rápido e sujo (o que você pediu), tudo bem.

Veja também este post em profundidade:

Gordon
fonte
3
Considere também a ArrayAccessinterface, talvez em combinação com esta solução. php.net/manual/en/class.arrayaccess.php
alttag
3
Se você tiver chaves inteiras, será convertido em string e isso pode causar um grande problema. Por exemplo, [1 => "one"]torna-se["1" => "one"]
Oleg
2
@Howie Typecasting com (array)e (object)funciona de maneira confiável e igual em todas as versões desde o PHP 4.3. Veja 3v4l.org/X6lhm . Se você receber um erro de sintaxe, fez algo errado.
Gordon
2
@Howie, consulte a seção Changelog paraempty . Você não pode usar uma expressão emptyanterior à 5.5. Isso não tem nenhuma relação com a tipografia;)
Gordon
4
Typecast. Sim. Digite Freakin CAST! Boa. +1
Kaushik Makwana
346

É possível converter rapidamente objetos profundamente aninhados em matrizes associativas, contando com o comportamento das funções de codificação / decodificação JSON:

$array = json_decode(json_encode($nested_object), true);
Jeff Standen
fonte
12
Esta é a melhor solução se você quiser uma conversão recursiva profundidade total (e, claro, não mente o mau desempenho)
Julian Habekost
2
isso me ajudou totalmente com a minha situação, muito obrigado.
César Bielich
9
Respeitosamente, acho que ainda funciona ... não se esqueça de definir o segundo parâmetro como true.
22415 Kirk B
3
O segundo parâmetro resolveu o problema, trabalhando no PHP 5.6.25. Obrigado!
Ju Oliveira
3
Funciona perfeito para objetos aninhados! Obrigado!
Melody
68

Desde o primeiro hit do Google para " objeto PHP para associar matriz ", temos o seguinte:

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

A fonte está em codesnippets.joyent.com .

István Ujj-Mészáros
fonte
16
Pessoalmente, não gosto da ideia de recuperar a função para cada valor. Eu tenho uma versão semelhante, mas em três linhas: function objectToArray($o) { $a = array(); foreach ($o as $k => $v) $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v; return $a; }isso apenas define qualquer coisa que não seja um objeto ou matriz e continua sem que o método seja invocado repetidamente, a menos que seja necessário.
SpYk3HH
13
@ SpYk3HH: escreva sua própria resposta?
DanMan 28/05
2
Primeiro hit de "objeto php a variedade assoc" é stackoverflow.com/questions/4345554/...
Chris
Isso (e a versão do @ SpYk3HH) parece ter um desempenho ainda mais lento para mim do que a opção json_encode ( stackoverflow.com/a/16111687/470749 ). Não sei por que essas abordagens seriam preferíveis.
Ryan
1
O @Ryan json codificar e decodificar não funcionará com os valores NaN e INFINITE para float e, potencialmente, pode ter outros problemas que não consigo pensar do alto da minha cabeça, mas, em muitos casos, pode ser uma opção melhor. Quanto à otimização, o que ele precisa é de contexto - deixe-me inserir um post que escrevi sobre esse assunto evidentlycube.com/blog/game-optimization/when-to-optimize . por exemplo, não otimize as coisas que não levam grande parte do tempo de execução, porque os benefícios são sem sentido no contexto de todo o aplicativo.
precisa
61

Se as propriedades do seu objeto forem públicas, você poderá:

$array =  (array) $object;

Se forem privados ou protegidos, terão nomes de chave estranhos na matriz. Portanto, neste caso, você precisará da seguinte função:

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.
fonte
Se sua propriedade estiver protegida, setAccessible (false) a alterará novamente para visibilidade protegida? ou vai torná-lo privado?
Nick Mitchell
A única solução que encontrei, que funcionava com propriedades protegidas. Graças
DAV
3
melhor solução para variáveis ​​privadas e protegidas !!
HIRA THAKUR 22/02
Aqui a linha $ property-> setAccessible (false); será executado em cada propriedade - mesmo que fosse público ...
François Bourgeois
Excelente ... Incrível ... Incrível. Obrigado.
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());

Resultado

array(2) {
    ["b"]=>
    string(3) "two"
    ["Testc"]=>
    int(1)
}
array(1) {
    ["b"]=>
    string(3) "two"
}
Isius
fonte
1
Prós e contras desta solução? Que tal uma classe declarada como classe Test {const A = 1; public $ parent = new Test (); }
Matteo Gaggiano 21/04
13

Aqui está um 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
fonte
funciona melhor para mim (mas eu precisava remover o 'xxx' e retornar os dados $)
Gerfried
12

Todas as outras respostas postadas aqui estão funcionando apenas com atributos públicos. Aqui está uma solução que funciona com objetos do tipo JavaBeans usando reflexão e 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
fonte
Sim, mas ... se você estiver usando o Object / Array como uma variável, e é isso que tudo isso leva também, por que você precisa de algo além das publicpropriedades?
SpYk3HH
@ SpYk3HH: Eu não fiz a pergunta. Nem sei por que alguém preferiria uma matriz a um objeto.
Francois Bourgeois
Eh, geralmente prefiro converter os resultados da consulta em array apenas para fornecer uma "lista" uniforme para repetição, pois a maioria das outras coisas em um aplicativo que deve ser "repetido" tendem a ser matrizes. Apenas facilita escrever "métodos de loop universal". Freqüentemente, se estou usando um objeto, não estou percorrendo suas propriedades, estou usando-o como objeto e usando essas propriedades conforme necessário.
SpYk3HH
11

Que tal get_object_vars($obj)? Parece útil se você deseja acessar apenas as propriedades públicas de um objeto.

Veja get_object_vars .

Joe
fonte
10

Digite converter seu objeto em uma matriz.

$arr =  (array) $Obj;

Isso resolverá o seu problema.

Adeel
fonte
5
Não, não terá, se você tiver propriedades particulares ou protegidas.
forsberg
2
Solução mais simples. Obrigado
ASD
6

Primeiro de tudo, se você precisar de uma matriz de um objeto, provavelmente deverá constituir os dados como uma matriz primeiro. Pense nisso.

Não use uma foreachdeclaração ou transformações JSON. Se você está planejando isso, novamente está trabalhando com uma estrutura de dados, não com um objeto.

Se você realmente precisar, use uma abordagem orientada a objetos para ter um código limpo e sustentável. Por exemplo:

Objeto como matriz

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

Se você precisar de todas as propriedades, use um objeto de transferência:

class PersonTransferObject
{
    private $person;

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

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

 }
John Smith
fonte
6

Você pode facilmente usar esta função para obter o 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 ou posterior.

Fiacre AYEDOUN
fonte
5

Aqui está minha função PHP recursiva para converter objetos PHP em uma matriz associativa:

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

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

Exemplo 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
fonte
3
.. ou o oneliner:$new_arr1 = (array) $my_object;
FooBar 03/03
1
A versão oneliner é rasa, portanto não é equivalente.
27615 Jonathan Lidbeck
5

Para converter um objeto em matriz, basta convertê-lo explicitamente:

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

Você também pode criar uma função no PHP para converter uma matriz de objetos:

function object_to_array($object) {
    return (array) $object;
}
Rakhi Prajapati
fonte
@ Akintunde-Rotimi, criei uma função comum e mostrei.
Rakhi Prajapati
4

Você pode fazer isso ao obter dados como objetos de bancos de dados:

// 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
fonte
2
Há uma resposta aceita com 41 votos positivos, não 1 ou 10, 41. O que sua resposta adiciona a ela?
Yaroslav #
4

Função personalizada para converter stdClass em uma 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;
    }
}

Outra função personalizada para converter Array em 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;
    }
}

Exemplo 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
fonte
4

Usar:

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

Retorna uma matriz sem caracteres especiais e nomes de classe.

ovnia
fonte
4

Esta resposta é apenas a união das diferentes respostas deste post, mas é a solução para converter um objeto PHP com propriedades públicas ou privadas com valores simples ou matrizes em uma matriz associativa ...

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

Alguns aprimoramentos no código "bem conhecido"

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

Observe que, se a função for membro de uma classe (como acima), você deverá alterar __FUNCTION__para__METHOD__

Gilbert BENABOU
fonte
3

Além disso, você pode usar o Symfony Serializer Component

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

Para o seu caso, era correto / bonito se você usasse os padrões "decorador" ou "transformação do modelo de data". Por exemplo:

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

Portanto, será um código mais bonito e mais correto.

Daniel Abyan
fonte
3

Convertendo e removendo estrelas irritantes:

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

Provavelmente, será mais barato do que usar reflexões.

Fedir RYKHTIK
fonte
2

Solução curta 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
fonte
2

Como muitas pessoas acham essa pergunta por causa de problemas com o acesso dinâmico aos atributos de um objeto, apenas mostrarei que você pode fazer isso no PHP: $valueRow->{"valueName"}

No contexto (saída HTML removida para facilitar a leitura):

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

Usando typecasting, você pode resolver seu problema. Basta adicionar as seguintes linhas ao seu objeto de retorno:

$arrObj = array(yourReturnedObject);

Você também pode adicionar um novo par de chave e valor usando:

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

Eu acho que é uma boa idéia usar características para armazenar a lógica de conversão de objeto em matriz. Um exemplo simples:

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
fonte
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
fonte
Estou assumindo que essa resposta é para um registro de Doutrina (ou similar).
Nikoskip
1

Aqui eu criei um método objectToArray () , que também funciona com objetos recursivos, como quando $objectAcontém $objectBquais pontos novamente $objectA.

Além disso, restringi a saída a propriedades públicas usando ReflectionClass. Livre-se disso, se você não precisar.

    /**
     * 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 já usados, estou usando uma propriedade protegida nesta classe (abstrata), denominada $this->usedObjects. Se um objeto aninhado recursivo for encontrado, ele será substituído pela sequência **recursive**. Caso contrário, ele falharia devido ao loop infinito.

Armin
fonte
$usedObjectsnão é inicializado no início, portanto, chamar isso várias vezes fornecerá resultados incorretos em chamadas posteriores. Além disso, você não o libera no final, para que seus objetos nunca sejam removidos da memória.
21419 HappyDog
1

Aqui está a minha proposta, se você tiver objetos em objetos com membros 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
fonte
1

Eu uso isso (solução recursiva necessária com chaves apropriadas):

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

Exemplo de uso, o seguinte 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)

Irá imprimir isto:

array(2) {
  ["bb"] => array(1) {
    ["two"] => int(22)
  }
  ["one"] => int(11)
}
ling
fonte
Como podemos atualizar sua função para suportar objetos com uma matriz de objetos?
celsowm