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.
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: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 incluidas 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:
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:
Fast PHP objecto to array conversion
Arrays type casting. Manual PHP.net
Función get_object_vars(). Manual PHP.net
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 incluidas 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 ( ):$theobject = new MyClass();
$thearray = (array) $theobject;
var_dump( $thearray );
/* Obtenmos
array(3) {
["a"] => int(1) // public
[" MyClass b"] => int(2) // private
[" * c"] => 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[" MyClass b"] y $thearray[" * c"] respectivamente.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
Fast PHP objecto to array conversion
Arrays type casting. Manual PHP.net
Función get_object_vars(). Manual PHP.net
Comentarios