26

i have a multidimensional array:

$image_path = array('sm'=>$sm,'lg'=>$lg,'secondary'=>$sec_image);

witch looks like this:

[_media_path:protected] => Array
            (
                [main_thumb] => http://example.com/e4150.jpg
                [main_large] => http://example.com/e4150.jpg
                [secondary] => Array
                    (
                        [0] => http://example.com/e4150.jpg
                        [1] => http://example.com/e4150.jpg
                        [2] => http://example.com/e9243.jpg
                        [3] => http://example.com/e9244.jpg
                    )

            )

and i would like to convert it into an object and retain the key names.

Any ideas?

Thanks

edit: $obj = (object)$image_path; doesn't seem to work. i need a different way of looping through the array and creating a object

Patrioticcow
  • 26,422
  • 75
  • 217
  • 337
  • can you give us a better example of what you want the object to look like? do you want to turn the keys into properties? for what purpose do you need an object? – mpen Feb 07 '12 at 01:38
  • instead of using `[]` to get the value i need to use `->` – Patrioticcow Feb 07 '12 at 01:42

2 Answers2

118

A quick way to do this is:

$obj = json_decode(json_encode($array));

Explanation

json_encode($array) will convert the entire multi-dimensional array to a JSON string. (php.net/json_encode)

json_decode($string) will convert the JSON string to a stdClass object. If you pass in TRUE as a second argument to json_decode, you'll get an associative array back. (php.net/json_decode)

I don't think the performance here vs recursively going through the array and converting everything is very noticeable, although I'd like to see some benchmarks of this. It works, and it's not going to go away.

Charlie Schliesser
  • 7,851
  • 4
  • 46
  • 76
  • 2
    This should be the answer, since the OP wants the whole multidimensional array, not the top-level array. – AeroCross Oct 09 '12 at 14:43
  • 2
    I would say that this is a slow way to do it. If performance is a concern, I would avoid this solution. – Caleb Taylor Feb 27 '13 at 15:43
  • @CalebTaylor – I hear ya. I'm not sure of the benchmarks, but am curious if there is a non-trivial difference between recursively iterating over a multi-dimensional array and adding to an object (i.e. doing this entire thing by hand) or simply running the above JSON trick. – Charlie Schliesser Feb 27 '13 at 16:47
  • Very cool, but I am finding that this fails to convert deeply nested multidimensional associative arrays into an object with properties. For instance, when I have an array, within an array, within an array, within an array (thats 4 deep), only the first two levels appear to convert arrays to objects. My hope was that this function could recursively change all nested arrays into objects. – Daniel Dropik Jun 02 '16 at 20:52
  • @DanielDropik Are the arrays that aren't being converted simple lists? I.e. *not* associative arrays but sequentially indexed? Check this example: http://codepad.org/sAOQgNgZ – Charlie Schliesser Jun 02 '16 at 21:12
  • This does not work if you have a mixed-index array. $a = ['some_key' => ['some value', 'some other value']]; php > print_r(json_decode(json_encode($a))); stdClass Object ( [some_key] => Array ( [0] => some value [1] => some other value ) ) – Paul Allsopp Feb 27 '18 at 18:37
  • I think what you're referencing is addressed in the 2 previous comments. What would you like/expect the keys to be for that list? 0, 1, etc? – Charlie Schliesser Feb 27 '18 at 18:41
  • 2
    I actually benchmarked this code with php 7.2 -> `json_decode` is 5 times faster than `array_map` or other recursive operations. Also in php 5.4 the `json_decode` solution is the fastest option I could find. Great answer! – Philipp Jul 12 '18 at 20:54
  • You also lose the object type if you have an array of objects. Ex: `['index1' => new Foo()]` you will get `{ ["index1"]=> array(0) { } }` – Mirceac21 Jul 21 '18 at 20:33
  • 1
    @Mirceac21 your object can implement [JsonSerializable](http://php.net/manual/en/jsonserializable.jsonserialize.php) to define how it's converted. – Charlie Schliesser Aug 21 '18 at 14:37
  • you my friend is awesome. tnx. :) – winnie damayo Apr 08 '19 at 05:43
7

The best way would be to manage your data structure as an object from the start if you have the ability:

$a = (object) array( ... ); $a->prop = $value; //and so on

But the quickest way would be the approach supplied by @CharlieS, using json_decode(json_encode($a)).

You could also run the array through a recursive function to accomplish the same. I have not benchmarked this against the json approach but:

function convert_array_to_obj_recursive($a) {
    if (is_array($a) ) {
        foreach($a as $k => $v) {
            if (is_integer($k)) {
                // only need this if you want to keep the array indexes separate
                // from the object notation: eg. $o->{1}
                $a['index'][$k] = convert_array_to_obj_recursive($v);
            }
            else {
                $a[$k] = convert_array_to_obj_recursive($v);
            }
        }

        return (object) $a;
    }

    // else maintain the type of $a
    return $a; 
}

Hope that helps.

EDIT: json_encode + json_decode will create an object as desired. But, if the array was numerical or mixed indexes (eg. array('a', 'b', 'foo'=>'bar') ), you will not be able to reference the numerical indexes with object notation (eg. $o->1 or $o[1]). the above function places all the numerical indexes into the 'index' property, which is itself a numerical array. so, you would then be able to do $o->index[1]. This keeps the distinction of a converted array from a created object and leaves the option to merge objects that may have numerical properties.

Wayne Weibel
  • 933
  • 1
  • 14
  • 22
  • Thanks for providing the recursive function, I think that's probably helpful to a lot of folks that stumble upon this. I'm going to check the PHP source code to see how json_encode/decode compares in terms of performance. I'm curious. – Charlie Schliesser Dec 23 '13 at 04:40
  • 4
    You can reference numerical properties on objects via `$o->{1}`. – Charlie Schliesser Feb 04 '14 at 15:35