984

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Haroldo
  • 36,607
  • 46
  • 127
  • 169

34 Answers34

1763

Just typecast it

$array = (array) $yourObject;

From Arrays:

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(
  )),
)

To know more about php built-in class stdclass. You can read this documentation

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:

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 1
    Ha, and I found a use for it already - see my answer to http://stackoverflow.com/questions/4352203/any-php-function-that-will-strip-properties-of-an-object-that-are-null/4352235#4352235 – El Yobo Dec 04 '10 at 06:18
  • 3
    Also consider the `ArrayAccess` interface, perhaps in combination with this solution. http://php.net/manual/en/class.arrayaccess.php – alttag Aug 08 '14 at 13:53
  • 1
    This will fail, if the object contains sub object which point back to the object which we are going to convert. This will cause an infinit loop. – Armin May 15 '15 at 00:00
  • 4
    It you have integer keys the'll be converted in to string and this can cause big issue. E.g. `[1 => "one"]` becomes `["1" => "one"]` – Oleg Aug 11 '15 at 12:16
  • 1
    @Oleg objects having numeric properties is a codesmell on it's own. – Gordon Aug 11 '15 at 12:23
  • 1
    @Gordon and how to convert it back to Collection Object? – Volatil3 Nov 29 '15 at 06:56
  • 1
    @Volatil3 to a StdClass object: `(object) $array`. Typecasting to any other object requires hackery: http://stackoverflow.com/questions/3243900/convert-cast-an-stdclass-object-to-another-class – Gordon Nov 29 '15 at 08:31
  • 3
    @Howie Typecasting with `(array)` and `(object)` works reliably and the same across all versions since PHP 4.3. See https://3v4l.org/X6lhm. If you get a syntax error, you did something wrong. – Gordon Nov 30 '15 at 10:26
  • 1
    @Gordon `if (!empty((array)$object))` on 5.3.28 generated an error, whilst the same thing on 5.5.x works just fine. I will inspect further, if I find the time. – Howie Dec 01 '15 at 10:05
  • 2
    @Howie see the [Changelog section for `empty`](http://php.net/manual/en/function.empty.php). You cannot use an expression with `empty` prior to 5.5. This is completely unrelated to typecasting ;) – Gordon Dec 01 '15 at 10:48
  • 1
    @Gordon Heh, so that was it. I'll leave my comments for future notice. Thanks! – Howie Dec 01 '15 at 12:53
  • 2
    Attention!!! Integer properties become unaccessible. Though they can be seen via print_r etc. – Vyshnia Aug 07 '18 at 11:05
  • 1
    @Vishnja Integer properties are not allowed in PHP. The only way to get them without causing an error is by json_decoding something like `{"0": 42}` in which case you can still access them by `$obj->{"0"}` – Gordon Aug 07 '18 at 11:36
  • 2
    @Gordon Yes, exactly. This brings confusion when somebody recieves object from some API, that really should be an array, decodes and converts it. And finally sees array elements but can not access them. – Vyshnia Aug 08 '18 at 12:23
  • 2
    @Vishnja well, you *can* access them. Like I said `$obj->{"0"}` will work :) – Gordon Aug 09 '18 at 06:27
  • does typecasting like this `(array) $object` ensure that the order in which the object attributes are assigned is maintained in the resulting array? – Jethro Cao Dec 06 '20 at 08:18
  • 1
    Not a good solution! It does not deep convert objects to arrays, which will NOT be acceptable when working with APIs (it might work for the most simple examples, but it won't otherwise). Why do people upvote this? – Lideln Kyoku Jun 13 '21 at 17:35
  • @LidelnKyoku because the OP asked for a quick and dirty solution and the answer clearly states that it's not deep converting. And I guess it solves the problem for most people that had the problem `¯\_(ツ)_/¯` – Gordon Jun 15 '21 at 07:49
  • Still there @Gordon ?! :) Yeah it does work in the most simple scenarios, but it won't otherwise, which means taking a risk (unless the user is 100% sure of what the API will return today and in the future). It's an accident waiting to happen IMHO. Anyway, stay safe, cheers Gordon! :) – Lideln Kyoku Jun 21 '21 at 11:48
  • OP asked for a quick-and-dirty solution, he got one. Thing is there is no problem having a problem in this solution. – Salman Malik Sep 14 '22 at 08:09
  • This does not work recursively. You will still have Objects serialized the descendant values if you use this method. – Xliff May 23 '23 at 22:49
  • @Xliff see above. The answer clearly states that it will not do deep casting. – Gordon May 24 '23 at 12:45
522

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);
Elia Weiss
  • 8,324
  • 13
  • 70
  • 110
Jeff Standen
  • 6,670
  • 1
  • 17
  • 18
101

From the first Google hit for "PHP object to assoc array" we have this:

/**
 * @param array|object $data
 * @return array
 */
function object_to_array($data)
{
    $result = [];
    foreach ($data as $key => $value)
    {
        $result[$key] = (is_array($value) || is_object($value)) ? object_to_array($value) : $value;
    }
    return $result;
}

The original source was from codesnippets.joyent.com and has been changed according to @SpYk3HH's comment; see also Object Iteration.


To compare it to the solution of json_decode & json_encode, this one seems faster. Here is a random benchmark (using the simple time measuring):

$obj = (object) [
    'name'    =>'Mike',
    'surname' =>'Jovanson',
    'age'     =>'45',
    'time'    =>1234567890,
    'country' =>'Germany',
];

##### 100 000 cycles ######
* json_decode(json_encode($var))   : 4.15 sec
* object_to_array($var)            : 0.93 sec
hakre
  • 193,403
  • 52
  • 435
  • 836
Maurycy
  • 1,324
  • 1
  • 11
  • 33
  • 20
    Personally, I don't like the idea of recalling the function for every value. I have a similar version, but in 3 lines: `function objectToArray($o) { $a = array(); foreach ($o as $k => $v) $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v; return $a; }` This just sets anything that's not an object or array and continues on without repetitive recall to the method unless necessary. – SpYk3HH Jan 17 '14 at 15:38
  • 22
    @SpYk3HH: write your own answer? – DanMan May 28 '14 at 08:49
  • 3
    First hit for "php object to assoc array" is http://stackoverflow.com/questions/4345554/convert-php-object-to-associative-array – Chris Mar 26 '17 at 02:08
  • This (and the version from @SpYk3HH) seems to perform even slower for me than the json_encode option (https://stackoverflow.com/a/16111687/470749). I don't know why these approaches would ever be preferable. – Ryan Jun 06 '18 at 22:25
  • 3
    @Ryan json encode and decode won't work with NaN and INFINITE values for float and potentially may have other issues I can't think of from the top of my head but for many cases it might be a better option. As for optimization, what it needs is context - let me plug a post I wrote on this subject https://www.evidentlycube.com/blog/game-optimization/when-to-optimize. the tl;dr being, don't optimize things that don't take huge chunk of the running time because the benefits are meaningless in the context of the whole application. – Maurycy Jun 07 '18 at 08:23
  • @Maurycy I agree with your summarized recommendation against needless optimization, but in my case, I only discovered how slow json encode and decode were *because* they were noticeably slowing down my page load times. So I needed to find a faster way. My new approach is that I pulled json encode and decode out of a loop so that I run them just once outside and then run a loop on their components. – Ryan Jun 07 '18 at 13:43
  • @SpYk3HH your approach integrated into answer. – T.Todua Jun 16 '21 at 11:12
  • Doesn't seem to work with private fields – Pablo Pazos Oct 07 '22 at 14:15
72

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;
}
Ramon K.
  • 3,402
  • 3
  • 20
  • 29
  • If your property is protected, will setAccessible(false) change it back to protected visibility? or will it make it private? – Nick Mitchell May 15 '14 at 02:05
  • The only solution I found, that worked with protected properties. Thanks – dav Jun 13 '14 at 03:19
  • 4
    best solution for private and protected variables!! – HIRA THAKUR Feb 22 '16 at 04:48
  • Here the line $property->setAccessible(false); will be executed on every property - even if it was public... – Francois Bourgeois Jun 24 '16 at 11:09
  • I suppose another approach would be to cast it as array, then strip the text prefix off the Private properties. A little less dangerous, as your method risks setting public properties private – Stephen R Jul 09 '18 at 15:23
  • not recursive, an object with a couple of levels of associated objects will just convert the top ones and not the associated objects – Pablo Pazos Oct 07 '22 at 14:24
16

What about get_object_vars($obj)? It seems useful if you only want to access the public properties of an object.

See get_object_vars.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Joe
  • 272
  • 2
  • 9
16
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"
}
Isius
  • 6,712
  • 2
  • 22
  • 31
14

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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Khalid
  • 149
  • 1
  • 2
13

Type cast your object to an array.

$arr =  (array) $Obj;

It will solve your problem.

doctorsherlock
  • 1,334
  • 4
  • 19
  • 41
Adeel
  • 605
  • 1
  • 6
  • 16
12

All other answers posted here are only working with public attributes. Here is one solution that works with JavaBeans-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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Francois Bourgeois
  • 3,650
  • 5
  • 30
  • 41
  • Yea, but ... if you're using the Object/Array as a variable, which is what all this leads too, why do you need anything other than the `public` properties? – SpYk3HH Jan 17 '14 at 15:37
  • @SpYk3HH: I did not ask the question. I don't even know why anyone would prefer an array over an object in the first place. – Francois Bourgeois Feb 04 '14 at 08:50
  • Eh, I often prefer to convert query results to array just to provide a uniform "list" for looping through, as most other thing in an app that must be "looped" tend to be arrays. Just makes it easy to write "universal loop methods". Often, if i'm making use of an object, I'm not looping through it's properties, I'm using it as an object and using those properties as needed. – SpYk3HH Feb 04 '14 at 15:49
  • 2
    "why anyone would prefer an array over an object" I want to write a method, which loops with foreach through the values of an object's properties to write them in an excel file. I want this method to be independent of the object so I can use it with different arrays. Therefore my object needs a _toArray() method – Calamity Jane Jul 07 '21 at 07:39
10

To convert an object into array just cast it explicitly:

$name_of_array = (array) $name_of_object;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
7

Use:

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;
}

It returns an array without special characters and class names.

Sebastian
  • 1,321
  • 9
  • 21
ovnia
  • 2,412
  • 4
  • 33
  • 54
7

You can also create a function in PHP to convert an object array:

function object_to_array($object) {
    return (array) $object;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rakhi Prajapati
  • 880
  • 1
  • 12
  • 24
  • I don't think that wrapping pre-existing solutions on this page as a custom function adds much value to this page. If I am being honest, I think it adds unnecessary bloat to an already bloated page. – mickmackusa Jan 22 '23 at 04:05
6

You can easily use this function to get the result:

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 or later.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
5

Here is my recursive PHP function to convert PHP objects to an associative array:

// ---------------------------------------------------------
// ----- 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;
}

// ---------------------------------------------------------
// ---------------------------------------------------------

Usage example:

// ---- 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);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rabatto
  • 51
  • 1
  • 2
5

Custom function to convert stdClass to an 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);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rounds
  • 1,879
  • 4
  • 19
  • 30
5

First of all, if you need an array from an object you probably should constitute the data as an array first. Think about it.

Don't use a 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 an object-oriented approach to have a clean and maintainable 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 a transfer object:

class PersonTransferObject
{
    private $person;

    public function __construct(Person $person) {
        $this->person = $person;
    }

    public function toArray() {
        return [
            // 'name' => $this->person->getName();
        ];
    }

 }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Smith
  • 1,091
  • 9
  • 17
  • So I would manually assign the wanted properties to array values? Yes that is possible, but I hoped I could avoid that by implementing a _toArray() method in my object, which accomplishes that without manually adding each property. – Calamity Jane Jul 07 '21 at 07:42
5

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;
}
Abdul Rehman
  • 1,662
  • 3
  • 22
  • 36
4

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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
metaldog
  • 71
  • 1
  • 2
4

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 to an 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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daniel Guerrero
  • 184
  • 1
  • 2
  • 8
4

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);
Andrey Nilov
  • 109
  • 5
4

I use this (needed recursive solution with proper keys):

    /**
     * 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;
    }

Example of usage, the following code:

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)

Will print this:

array(2) {
  ["bb"] => array(1) {
    ["two"] => int(22)
  }
  ["one"] => int(11)
}

ling
  • 9,545
  • 4
  • 52
  • 49
3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fedir RYKHTIK
  • 9,844
  • 6
  • 58
  • 68
3

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__

3

For your case it was right/beautiful if you would use the "decorator" or "date model transformation" patterns. For example:

Your model

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;
    }
}

Decorator

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(),
        ];
    }
}

Usage

$car = new Car();
$car->setType('type#');
$car->setModel('model#1');
$car->setColor(255);

$carDecorator = new CarArrayDecorator($car);
$carResponseData = $carDecorator->getArray();

So it will be more beautiful and more correct code.

Daniel Abyan
  • 303
  • 2
  • 6
2

Since a lot of people find this question 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 .= " ";
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

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;
}
Karol Gasienica
  • 2,825
  • 24
  • 36
2

I think it is a nice idea to use traits to store object-to-array converting logic. A simple example:

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());
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1
$Menu = new Admin_Model_DbTable_Menu(); 
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu(); 
$Addmenu->populate($row->toArray());
Saurabh Chandra Patel
  • 12,712
  • 6
  • 88
  • 78
1

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.

Armin
  • 15,582
  • 10
  • 47
  • 64
  • `$usedObjects` is not initialised at the start, so calling this multiple times will give incorrect results in later calls. Also, you don't free it up at the end, so your objects will never be removed from memory. – HappyDog Jun 17 '19 at 12:43
1

By using typecasting you can resolve your problem. Just add the following lines to your return object:

$arrObj = array(yourReturnedObject);

You can also add a new key and value pair to it by using:

$arrObj['key'] = value;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Naveen Gupta
  • 306
  • 3
  • 11
0

Not a new solution but includes toArray method conversion when available

function objectToArray($r)
{
  if (is_object($r)) {
    if (method_exists($r, 'toArray')) {
      return $r->toArray(); // returns result directly
    } else {
      $r = get_object_vars($r);
    }
  }

  if (is_array($r)) {
    $r = array_map(__FUNCTION__, $r); // recursive function call
  }

  return $r;
}
Heroselohim
  • 1,241
  • 1
  • 18
  • 23
0
function object_to_array(array|object $data) : array {
  $result = (array) $data;  
  foreach ($result as $key => $value) {
    if (is_object($value))
      $value = (array) $value;
    if (is_array($value))
      $result[$key] = object_to_array($value);
  }
  return $result;
}

Example:

class x {
  var $a = "hello";
}
class y {
   var $b = 1;
   var $c = 2;
   var $d = "abc";
   var $e = null;
   public function __construct() {
       $this->e = new x();
   }
}

var_dump(object_to_array(new y()));

Output:

array(4) {
  ["b"]=> int(1)
  ["c"]=> int(2)
  ["d"]=> string(3) "abc"
  ["e"]=> array(1) {
    ["a"]=> string(5) "hello"
  }
}
Frank
  • 1,901
  • 20
  • 27
  • \u0000 is appearing with all property names and their values. Can we avoid it? Also name of the class appears with all properties – Syed Irfan Ahmad Jul 20 '23 at 11:23
  • @Syed there is no name of a class on the result, there is only the name "a" from the property "a" from class "y". – Frank Aug 03 '23 at 19:34
  • First, this code is incorrect as it fails to convert some nested objects. Second, it's just incorrect implementation of existing answer. Please read other answers before posting your own. – Your Common Sense Aug 11 '23 at 07:17
  • first, nested objects are not failed. second, if you meen the problem with private/protected properties than you are right. But then you must make an discussion: Is an private property realy "exportable"? – Frank Aug 11 '23 at 10:50
-2

I tested it in Laravel Collections, this is working well.

function objectToArray($data)
{
    if (is_array($data) || is_object($data))
    {
        $result = [];
        foreach ($data as $key => $value)
        {
            $result[$key] = (is_array($data) || is_object($data)) ? objectToArray($value) : $value;
        }
        return $result;
    }
    return $data;
}
Amir Hosseinzadeh
  • 7,360
  • 4
  • 18
  • 33
-4

To convert an object to an array in PHP, you can use the json_decode() function in combination with json_encode(). Here's an example:

// Assuming $object is your object
$jsonString = json_encode($object);
$array = json_decode($jsonString, true);

In the above example, json_encode($object) converts the object into a JSON string. Then, json_decode($jsonString, true) converts the JSON string back into an associative array by passing true as the second argument.

After executing this code, the $array variable will contain the array representation of the object.

Keep in mind that this method works for most cases, but it may not preserve some object-specific features like private properties or methods.

If you're using PHP 7.4 or later, you can also use the get_object_vars() function to convert an object to an array. Here's an alternative example:

// Assuming $object is your object
$array = get_object_vars($object);

In this case, get_object_vars($object) directly returns an associative array representation of the object, where the array keys correspond to the object's property names.

Choose the method that best suits your needs based on your PHP version and specific requirements.