pasar from convertir convert array php arrays object casting

php - from - Casting object to array: ¿se llama a cualquier método mágico?



object to array php laravel (6)

Tengo un objeto de clase Foo:

class Foo extends Bar { protected $a; protected $b; } $obj = new Foo();

Lo que quiero (y tengo) que hacer es convertir este objeto en una matriz, como esta:

$arr = (array)$obj;

¿Hay algún método mágico (o no mágico :)) que se llame en este momento? ¿O hay alguna otra forma de interceptarlo? Sé que puedo escribir un método simple, por ej. asArray() en Foo, pero estoy buscando formas PHP más "nativas".


No

No existe el método mágico __toArray en PHP. Una propuesta de mejora fue rechazada en 2006 con la siguiente respuesta:

[2006-08-20 11:12 UTC] [email protected]

¿Por qué no simplemente tener un método como Array () tal vez incluso como parte de una interfaz?

interfaz ArrayConversion {function asArray (); }

Mira, tenemos __toString ya que está soportado en construcciones de lenguaje como eco, impresión y otras funciones internas. Pero decidimos evitar una autoconversión para matrices. Por lo tanto, nunca se admitirá en ninguna construcción de lenguaje. Dicho esto, no es necesario para esto y nada que ganarías contra la interfaz anterior. De hecho, harías que php sea más complejo porque agregarías solo una característica mágica más.

Por lo tanto, es muy poco probable que se implemente en cualquier versión futura (lo cual es una lástima, si me preguntas).


Lamentablemente, no, lanzar al array no activa ningún método mágico como el que se hace con:

$s = (string)$obj;

que activa el método __toString() y que puede anular.

Sin embargo, puede escribir un toArray() personalizado en toArray() .

También puede interesarle la interfaz Serializable que le permite escribir una estrategia de serializador personalizado.


No estoy seguro si esta pregunta sigue siendo relevante, pero php tiene incorporada la clase /ArrayObject , que permite tratar el objeto como una matriz y puede ser útil cuando se utiliza como contenedor para el registro o la recopilación de la base de datos.

Puede que no sea una buena práctica en cuanto a tipos estrictos, pero permite tratar objetos como una matriz y ambas declaraciones son válidas.

$obj = new ArrayObject([''a'' => ''alpha'']); var_dump($obj[''a'']); //alpha var_dump($obj->getOffset(''a''));//alpha

Sin embargo, debe tener en cuenta el comportamiento de ArrayObject

$obj = new ArrayObject([''a'' => ''alpha'']); //Access Property var_dump($obj[''a'']); //alpha var_dump($obj->offsetGet(''a''));//alpha var_dump($obj->a); //null Notice: Undefined property: ArrayObject::$a //Serialization var_dump(serialize($obj));// string ''C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}'' (length=65) var_dump($obj->serialize());// string ''x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'' var_dump(serialize($obj) === $obj->serialize());// false !!! //Setting Properties $obj[''b''] = ''beta''; //OK $obj->c = ''gamma''; //value becomes object property!!! var_dump($obj); /* OBJECT DUMP object(ArrayObject)[13] public ''c'' => string ''gamma'' (length=5) private ''storage'' => array (size=2) ''a'' => string ''alpha'' (length=5) ''b'' => string ''beta'' (length=4) */ //Property validation as array var_dump(isset($obj[''a'']));//true var_dump(isset($obj[''b'']));//true var_dump(isset($obj[''c'']));//false //Property validation as object var_dump(isset($obj->a));//false var_dump(isset($obj->b));//false var_dump(isset($obj->c));//true //Typecasting var_dump((array)$obj); /* array (size=2) ''a'' => string ''alpha'' (length=5) ''b'' => string ''beta'' (length=4) */ //var_dump((string)$obj);// Catchable fatal error: Object of class ArrayObject could not be converted to string

ArrayObject acepta dos indicadores ArrayObject::STD_PROP_LIST como predeterminado y ArrayObject::ARRAY_AS_PROPS como alternativa.

Esto cambiaría el comportamiento de los valores de lectura pero no permite establecer nuevas propiedades de esa manera, aquí hay un ejemplo:

$obj = new ArrayObject([''a'' => ''alpha''], ArrayObject::ARRAY_AS_PROPS); //Access Property var_dump($obj[''a'']); //alpha var_dump($obj->offsetGet(''a''));//alpha var_dump($obj->a);//alpha //Serialization var_dump(serialize($obj));// string ''C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}'' (length=65) var_dump($obj->serialize());// string ''x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'' var_dump(serialize($obj) === $obj->serialize());// false !!! //Setting Properties $obj[''b''] = ''beta''; //OK $obj->c = ''gamma''; //OK var_dump($obj); /* OBJECT DUMP object(ArrayObject)[14] private ''storage'' => array (size=3) ''a'' => string ''alpha'' (length=5) ''b'' => string ''beta'' (length=4) ''c'' => string ''gamma'' (length=5) */ //Property validation as array var_dump(isset($obj[''a'']));//true var_dump(isset($obj[''b'']));//true var_dump(isset($obj[''c'']));//false !!! //Property validation as object var_dump(isset($obj->a));//true var_dump(isset($obj->b));//true var_dump(isset($obj->c));//true //Typecasting var_dump((array)$obj); /* array (size=2) ''a'' => string ''alpha'' (length=5) ''b'' => string ''beta'' (length=4) */

Para que este comportamiento sea más consistente, tendrías que extender esta clase e implementar los métodos mágicos __get() , __set() , __isset() y __unset() .

Otra parte complicada es la serialización, el método predeterminado serialize devolvería una copia serializada $storage variable de $storage lugar del objeto en sí, como solución alternativa para devolver una copia serializada de la instancia puede implementar la serialización predeterminada en el método __toString , de esta manera se comporta correctamente.

class FooObject extends ArrayObject { public function __get($index) { if ($this->offsetExists($index)) { return $this->offsetGet($index); } else { throw new UnexpectedValueException(''Undefined key '' . $index); } } public function __set($index, $value) { $this->offsetSet($index, $value); return $this; } public function __isset($index) { return $this->offsetExists($index); } public function __unset($index) { return $this->offsetUnset($index); } public function __toString() { return serialize($this); } }

Ejemplo de uso

$obj2 = new FooObject([''a'' => ''alpha'']); //Access Property var_dump($obj2[''a'']); //alpha var_dump($obj2->offsetGet(''a''));//alpha var_dump($obj2->a); //alpha //Serialization var_dump(serialize($obj));// string ''C:11:"ArrayObject":41:{x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}}'' (length=65) var_dump($obj->serialize());// string ''x:i:0;a:1:{s:1:"a";s:5:"alpha";};m:a:0:{}'' var_dump(serialize($obj) === $obj->serialize());// false !!! //Setting Properties $obj2[''b''] = ''beta''; //OK $obj2->c = ''gamma''; //OK var_dump($obj2); /* OBJECT DUMP object(FooObject)[14] private ''storage'' (ArrayObject) => array (size=3) ''a'' => string ''alpha'' (length=5) ''b'' => string ''beta'' (length=4) ''c'' => string ''gamma'' (length=5) */ //Property validation as array var_dump(isset($obj2[''a'']));//true var_dump(isset($obj2[''b'']));//true var_dump(isset($obj2[''c'']));//true //Property validation as object var_dump(isset($obj2->a));//true var_dump(isset($obj2->b));//true var_dump(isset($obj2->c));//true //Typecasting var_dump((array)$obj2); /* array (size=3) ''a'' => string ''alpha'' (length=5) ''b'' => string ''beta'' (length=4) ''c'' => string ''gamma'' (length=5) */


Puede hacer que la clase implemente la interfaz ArrayAccess . Esto le permitirá tratar el objeto como una matriz sin lanzar y tendrá control total sobre cómo se usan los miembros.


Puede usar get_object_vars ($ yourObject) que devolverá una matriz asociativa de todos los nombres / valores de propiedades accesibles desde el contexto.

Ver http://php.net/manual/en/function.get-object-vars.php

A si desea acceder a propiedades protegidas o privadas, mi consejo sería ampliar ArrayObject, que implementa el método getArrayCopy ()


Una forma de hacer esto, sin cambiar la definición de clase original es usar la reflexión. Esto le permite examinar las propiedades de la clase en tiempo de ejecución.

Tomado del manual: http://www.php.net/manual/en/reflectionclass.getproperties.php

<?php class Foo { public $foo = 1; protected $bar = 2; private $baz = 3; } $foo = new Foo(); $reflect = new ReflectionClass($foo); $props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED); foreach ($props as $prop) { print $prop->getName() . "/n"; } var_dump($props); ?> The above example will output something similar to: foo bar array(2) { [0]=> object(ReflectionProperty)#3 (2) { ["name"]=> string(3) "foo" ["class"]=> string(3) "Foo" } [1]=> object(ReflectionProperty)#4 (2) { ["name"]=> string(3) "bar" ["class"]=> string(3) "Foo" } }