Respostas:
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_export
vez 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:
[1 => "one"]
torna-se["1" => "one"]
(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.
empty
. Você não pode usar uma expressão empty
anterior à 5.5. Isso não tem nenhuma relação com a tipografia;)
É 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);
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 .
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.
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;
}
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"
}
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;
}
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;
}
public
propriedades?
Que tal get_object_vars($obj)
? Parece útil se você deseja acessar apenas as propriedades públicas de um objeto.
Veja get_object_vars .
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 foreach
declaraçã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();
];
}
}
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.
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);
$new_arr1 = (array) $my_object;
Para converter um objeto em matriz, basta convertê-lo explicitamente:
$name_of_array = (array) $name_of_object;
Você também pode criar uma função no PHP para converter uma matriz de objetos:
function object_to_array($object) {
return (array) $object;
}
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;
}
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);
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.
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;
}
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__
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);
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.
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.
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 .= " ";
}
}
}
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;
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());
$Menu = new Admin_Model_DbTable_Menu();
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu();
$Addmenu->populate($row->toArray());
Aqui eu criei um método objectToArray () , que também funciona com objetos recursivos, como quando $objectA
contém $objectB
quais 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.
$usedObjects
nã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.
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;
}
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)
}
ArrayAccess
interface, talvez em combinação com esta solução. php.net/manual/en/class.arrayaccess.php