Convertir objetos en arrays con PHP puede ser una tarea tan sumamente sencilla que hasta puede sorprender. Por ejemplo, se puede hacer un simple type casting (forzado de tipos) y listo. Sin embargo, si estamos ante objetos complejos, multidimensionales y con propiedades privadas o protegidas, la cosa puede ser un poco más complicada, aunque tampoco mucho. En cualquier caso, al final de este post sabrás como enfrentarte a ellos para realizar la conversión.

1

Objetos y arrays simples

Si tenemos un objeto simple, unidimensional, obtendremos igualmente un array unidimensional. Se puede hacer con dos métodos: (array) type casting y con la función get_ object_vars(). El array resultante es un array asociativo con los key construidos con el nombre de la propiedades del objeto.

Por ejemplo, supongamos que tenemos este objeto:

class MyClass {

  public $a = 1;
  public $b = 2;
  public $c = 3;
  public $d = 4;

}

Lo podemos convertir a un array con cualquiera de los dos métodos y obtendremos el mismo resultado:

$theobject = new MyClass();

$thearray = (array) $theobject;
var_dump( $thearray );

$thearray = get_object_vars( $theobject );
var_dump( $thearray );

// En ambos casos se obtiene
/*
array(4) {
  ["a"]=> int(1)
  ["b"]=> int(2)
  ["c"]=> int(3)
  ["d"]=> int(4)
}
*/

Ninguno de los métodos hace una conversión profunda ante un objeto multidimensional. Esto implica que si hay un objeto anidado, seguirá siendo un objeto anidado en el array resultante. Por ejemplo:

class MyClass {
  public $a;
  public $b;
  public $c;
  public $d;

  public function __construct() {
    $this->a = 1;
    $this->b = 2;
    $this->c = new StdClass;
    $this->c->bar = 3;
    $this->d = 5;
  }
}

$theobject = new MyClass();

$thearray = (array) $theobject;
var_dump( $thearray );

$thearray = get_object_vars( $theobject );
var_dump( $thearray );

// En ambos casos se obtiene lo siguiente
// Nota como el elemento "c" es un objeto no convertido en array
/*
array(4) {
  ["a"] => int(1)
  ["b"] => int(2)
  ["c"] => object(stdClass)#2 (1) {
    ["bar"]=> int(3)
  }
  ["d"] => int(5)
}
*/

Propiedades privadas, protegidas y estáticas

En los ejemplos anteriores todas las propiedades del objeto eran públicas y ambos métodos se comportaban igual. También se comportan igual ante propiedades estáticas, que no son incluídas en el array final. Pero si el objeto contiene propiedades privadas o protegidas se obtienen resultados muy diferentes con cada método. Por ejemplo, supongamos que tenemos el siguiente objeto:

class MyClass {

  public $a = 1;
  private $b = 2;
  protected $c = 3;
  static $d = 4;

}

Si se utiliza get_object_vars(), el array resultante contendrá sólo los elementos públicamente accesibles y no estáticos:

$theobject = new MyClass();
$thearray = get_object_vars( $theobject );

var_dump( $thearray );
/*
 Obtenemos
 array(1) {
   ["a"] => int(1)
 } 
*/

Pero si se utiliza el forzado de tipos, el array resultante contendrá todos los elementos no estáticos del objeto, incluyendo los privados y protegidos. Es muy importante notar que los key de los elementos privados y protegidos no se devuelven tal cual. A los elementos privados se le antepone el nombre de la clase y a los elementos protegidos se le antepone el símbolo *; además estas anteposiciones van delimitadas por null bytes (\0):

$theobject = new MyClass();
$thearray = (array) $theobject;

var_dump( $thearray );
/* Obtenmos
array(3) {
  ["a"]       => int(1)     // public
  ["\0MyClass\0b"] => int(2) // private
  ["\0*\0c"]      => int(3) // protected
} 
*/

Es muy importante recordar los null bytes introducidos. Si intentas acceder a $thearray["MyClassb"] o $thearray["*c"] obtendrás un error tipo warning undefined index (o null si tienes este tipo de errores apagados). Recuerda introducir los null bytes delimitadores; en este ejemplo habría que utilizar $thearray["\0MyClass\0b"] y $thearray["\0*\0c"] respectivamente.

2

Objetos y arrays multidimensionales

Si queremos pasar un objeto multidimensional a un array multidimensional, es decir, realizar una conversión profunda, es necesario algún tipo de itinerancia utilizando alguno de los métodos explicados anteriormente. Por ejemplo, con esta función:

function objectToArray ( $object ) {

  if(!is_object($object) && !is_array($object)) {

    return $object;

  }
  
  return array_map( 'objectToArray', (array) $object );

}

En la función anterior se utiliza el type casting para convertir el objeto en array pero podrías cambiar sin problemas a get_object_vars() si lo necesitas. Pero como get_object_vars() devuelve el array sólo con los elementos públicos del objeto, puede ser más interesante utilizar json_decode() y json_encode() para realizar la conversión y obtener el mismo resultado. La clave está en establecer en true el segundo parámetro de json_decode() para que se devuelva un array en lugar de un objeto.

$array = json_decode( json_encode( $object ), true );

Referencias

  1. Fast PHP objecto to array conversion
  2. Arrays type casting. Manual PHP.net
  3. Función get_object_vars(). Manual PHP.net
  • Mario German

    Hola Juan: Tengo la siguiente duda, estoy interesado en convertir json_decode en array multidimensional php, como debo hacerlo, podrías hacer un ejemplo, agradezco toda tu colaboración, gracias.

    • Hola Mario,

      No entiendo muy bien lo que preguntas.

      Por un lado, json_decode() es una función y no se puede transformar una función en un array. Imagino que habrá sido un lapsus de expresión y que no querías decir eso realmente ;).

      Por otro lado, json_decode() trasforma un string JSON en un objeto o, si como se como explica en el post se establece el segundo parámetro como true, en un array. En cualquier caso mantiene la misma estructura que el objeto JSON original; si este objeto era multidimensional, el array obtenido será multidimensional.

      Espero haberme explicado bien y que entiendas lo que quiero decir.