I'm integrating an API to my website which works with data stored in objects while my code is written using arrays.
I'd like a quick and dirty function to convert an object to an array.
转载于:https://stackoverflow.com/questions/4345554/convert-php-object-to-associative-array
Just typecast it
$array = (array) $yourObject;
From http://www.php.net/manual/en/language.types.array.php
If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side.
Example: Simple Object
$object = new StdClass;
$object->foo = 1;
$object->bar = 2;
var_dump( (array) $object );
Output:
array(2) {
'foo' => int(1)
'bar' => int(2)
}
Example: Complex Object
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 );
Output (with \0s edited in for clarity):
array(3) {
'\0Foo\0foo' => int(1)
'\0*\0bar' => int(2)
'baz' => class stdClass#2 (0) {}
}
Output with var_export
instead of var_dump
:
array (
'' . "\0" . 'Foo' . "\0" . 'foo' => 1,
'' . "\0" . '*' . "\0" . 'bar' => 2,
'baz' =>
stdClass::__set_state(array(
)),
)
Typecasting this way will not do deep casting of the object graph and you need to apply the null bytes (as explained in the manual quote) to access any non-public attributes. So this works best when casting StdClass objects or objects with only public properties. For quick and dirty (what you asked for) it's fine.
Also see this in-depth blog post:
Type cast your object to an array.
$arr = (array) $Obj;
It will solve your problem.
Here is some code:
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;
}
You might want to do this when you obtain data as objects from databases -->
// 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;
}
All other answers posted here are only working with public attributes. Here is one solution that works with javabean-like objects using reflection and 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;
}
If your object properties are public you can do:
$array = (array) $object;
If they are private or protected, they will have weird key names on the array. So, in this case you will need the following function:
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;
}
You can quickly convert deeply nested objects to associative arrays by relying on the behavior of the JSON encode/decode functions:
$array = json_decode(json_encode($nested_object), true);
What about get_object_vars($obj)
? Seems useful if you only want to access the public properties of an object. http://www.php.net/function.get-object-vars
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());
Output
array(2) {
["b"]=>
string(3) "two"
["Testc"]=>
int(1)
}
array(1) {
["b"]=>
string(3) "two"
}
Converting and removing annoying stars :
$array = (array) $object;
foreach($array as $key => $val)
{
$new_array[str_replace('*_','',$key)] = $val;
}
Probably, it will be cheaper than using reflections.
Hi,
Here is my recursive PHP function to convert PHP objects to an associative array
// ---------------------------------------------------------
// ----- object_to_array_recusive --- 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_recusive ( $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_recusive($val);
}
else {
$res_arr[$akey] = (empty($val)) ? $empty : (string)$val;
}
$i++;
}
}
return $res_arr;
}
// ---------------------------------------------------------
// ---------------------------------------------------------
Usage example:
// ---- return associative array from object, ... use:
$new_arr1 = object_to_array_recusive($my_object);
// -- or --
// $new_arr1 = object_to_array_recusive($my_object,TRUE);
// -- or --
// $new_arr1 = object_to_array_recusive($my_object,1);
// ---- return numeric array from object, ... use:
$new_arr2 = object_to_array_recusive($my_object,FALSE);
Custom Function to convert stdClass to array:
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;
}
}
Another custom function to convert Array to 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;
}
}
Usage Example:
// 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);
$Menu = new Admin_Model_DbTable_Menu();
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu();
$Addmenu->populate($row->toArray());
function readObject($object) {
$name = get_class ($object);
$name = str_replace('\\', "\\\\", $name); \\ Comment this line, if you dont 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;
}
returns array without special characters and class names
Here I've made an objectToArray() method, which also works with recursive objects, like when $objectA
contains $objectB
which points again to $objectA
.
Additionally I've restricted the output to public properties using ReflectionClass. Get rid of it, if you don't need it.
/**
* 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;
}
To identify already used objects, I am using a protected property in this (abstract) class, named $this->usedObjects
. If a recursive nested object is found, it will be replaced by the string **recursive**
. Otherwise it would fail in because of infinite loop.
To convert an object into array just cast it explicitly
$name_of_array = (array) $name_of_object;
Some impovements to the "well-knwon" code
/*** 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
Notice that if the function is member of a class (like above) you must change __FUNCTION__
to __METHOD__
From the first Google hit for "php object to assoc array" we have this:
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;
}
Source at codesnippets.joyent.com.
First of all, if you need an array from object you probably should constitutes the data as array first. Think about it.
Don't use foreach statement or JSON transformations. If you're planning this, again you're working with a data structure, not with an object.
If you really need it use object orientated approach to have a clean and maintable code. For example:
Object as array
class PersonArray implements \ArrayAccess, \IteratorAggregate
{
public function __construct(Person $person) {
$this->person = $person;
}
// ...
}
If you need all properties use transfer object
class PersonTransferObject
{
private $person;
public function __construct(Person $person) {
$this->person = $person;
}
public function toArray() {
return [
// 'name' => $this->person->getName();
];
}
}
Since a lot of people find this thread because of having trouble with dynamically access attributes of an object, I will just point out that you can do this in php: $valueRow->{"valueName"}
In Context (removed HTML output for readability):
$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 .= " ";
}
}
}
this function can convert object proprity to array associatif
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 >= php5
This answer is only the union of the different answers of this post, but it's the solution to convert a PHP object with public or private properties with simple values or arrays in associative array ...
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;
}
Short solution of @SpYk3HH
function objectToArray($o)
{
$a = array();
foreach ($o as $k => $v)
$a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v;
return $a;
}
Also you can use The 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);
You can also create function in PHP to convert object array.
function object_to_array($object) {
return (array) $object;
}
By using typecasting you can resolve your problem. Just add following lines to your return object :
$arrObj = array(yourReturnedObject);
you can also add new key and value pair to it by using:
$arrObj['key'] = value;
There's my proposal, if you have objects in objects with even private members:
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;
}