68

In PHP, I can specify array literals quite easily:

array(
    array("name" => "John", "hobby" => "hiking"),
    array("name" => "Jane", "hobby" => "dancing"),
    ...
)

But what if I want array of objects? How can I specify object literal in PHP? I.e. in javascript it would be:

[
    {name: "John", hobby: "hiking"},
    {name: "Jane", hobby: "dancing"}
]
Tomas
  • 57,621
  • 49
  • 238
  • 373
  • 5
    There is no object literal in PHP. – BoltClock Mar 10 '12 at 07:57
  • 1
    @ŠimeVidas, I don't understand your comment. JS objects is associative arrays, but PHP associative arrays are not objects. Also PHP is not ECMAScript language, and PHP is not even JS. – Dima Zorin Dec 24 '12 at 15:33
  • @DmitryZorin I see. I thought that PHP associative arrays *are* objects (like in JavaScript). – Šime Vidas Dec 24 '12 at 16:43
  • @ŠimeVidas I understand what you are saying but what you must understand is how the two different langauges are interpreted, which is very different. – GriffLab Jul 27 '13 at 06:32
  • 3
    @ŠimeVidas I think TMS was showing how to do it in JavaScript as an illustration. So the question is "how do I do the same in PHP?" – Stewart Aug 27 '16 at 17:11
  • Possible duplicate of [Does PHP feature short hand syntax for objects?](http://stackoverflow.com/questions/455800/does-php-feature-short-hand-syntax-for-objects) – faintsignal Nov 22 '16 at 17:56

10 Answers10

97

As BoltClock mentioned there is no object literal in PHP however you can do this by simply type casting the arrays to objects:

$testArray = array(
    (object)array("name" => "John", "hobby" => "hiking"),
    (object)array("name" => "Jane", "hobby" => "dancing")
);

echo "Person 1 Name: ".$testArray[0]->name;
echo "Person 2 Hobby: ".$testArray[1]->hobby;
Tim
  • 7,660
  • 3
  • 30
  • 33
  • 13
    Do note that objects are always passed by reference, arrays are not. So changing an attribute of an object changes it everywhere the object has been assigned. This is not the case for arrays; they remain independent. – Gregory Cosmo Haun Mar 18 '14 at 23:08
  • 1
    @GregoryCosmoHaun Objects are not passed by reference. They are passed by a numeric value called object identifier. Which allows object accessors to find the actual object. – Rain Nov 14 '20 at 20:57
  • @Rain What is the difference? An "object identifier" that refers to a particular object is a reference to the object, isn't it? – Stack Underflow Jan 06 '21 at 17:15
  • 1
    @Stack-Underflow You can see how these techniques are different here https://3v4l.org/hkOcA – Rain Jan 06 '21 at 20:10
  • 1
    @Rain the example you linked has a typo that obscures what you were trying to show. Here's a corrected version: https://3v4l.org/njjm6. – David P. Caldwell Oct 03 '22 at 10:37
  • @DavidP.Caldwell,@Rain The examnple clearly shows that objects are passed by reference. You are confusing passing an object by reference with passing a reference to a variable. This works like in practically other language, calling a reference an "identifier" might be a PHP quirk, but it does not change that it is pass by reference. – Remember Monica Nov 18 '22 at 12:51
68

As of PHP 5.4 you can also use the short array syntax:

$json = [
    (object) ['name' => 'John', 'hobby' => 'hiking'],
    (object) ['name' => 'Jane', 'hobby' => 'dancing'],
];
mipaaa
  • 797
  • 5
  • 7
16

As others have noted, there is no object literal in PHP, but you can "fake" it by casting an array to an object.

With PHP 5.4, this is even more concise, because arrays can be declared with square brackets. For example:

$obj = (object)[
    "foo" => "bar",
    "bar" => "foo",
];

This would give you an object with "foo" and "bar" properties. However, I don't think this really provides much advantage over using associative arrays. It's just a syntax difference.

Consider embracing the uniqueness and "flavor" of all the languages you use. In JavaScript, object literals are all over the place. In PHP, associative arrays are functionally the same as JavaScript object literals, are easy to create, and are well understood by other PHP programmers. I think you're better off embracing this "flavor" than trying to make it feel like JavaScript's object literal syntax.

Josh
  • 7,232
  • 8
  • 48
  • 75
4

Another way would be to use the __set_state() magic method:

$object = stdClass::__set_state (array (
    'height'   => -10924,
    'color'    => 'purple',
    'happy'    => false,
    'video-yt' => 'AgcnU74Ld8Q'
));

Some more on the __set_state() method, where is it coming from and how is it supposed to be used.

Septagram
  • 9,425
  • 13
  • 50
  • 81
  • 3
    -1, This would be cool if it worked. However, `stdClass` does not have a defined `__set_state` method. – Shad Mar 18 '13 at 20:31
4

Although casting as an (object) works fine on a single hierarchical level, it doesn't go deep. In other words, if we want objects at every level, we'd have to do something like:

$foods = (object)[
  "fruits" => (object)["apple" => 1, "banana" => 2, "cherry" => 3],
  "vegetables" => (object)["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
];

However, instead of doing multiple casting as objects, we can wrap the whole thing in a json_encode and json_decode like this:

$foods = json_decode(json_encode([
  "fruits" => ["apple" => 1, "banana" => 2, "cherry" => 3],
  "vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
]));

That makes sure it's an object at the deepest level.

To answer klewis, you can then access this like:

echo $foods->vegetables->broccoli;

This example would output the number 5.

Dave Lampert
  • 191
  • 2
  • 3
  • Nice solutions, can you provide a simple example with your second option in referencing the value of broccoli in an echo statement? – klewis Jan 29 '20 at 12:24
  • 1
    ` ["apple" => 1, "banana" => 2, "cherry" => 3], "vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6] ])); echo $foods->vegetables->broccoli; ?>` should output the number 5 – Dave Lampert Jan 30 '20 at 14:35
  • by far the best answer on this thread for thoughe coming from a javascript background and want either a single level or deep level approach. – klewis Jan 30 '20 at 16:08
2

My way of JavaScript-style object literals in PHP is as follows:

First I create an associative array like this:

$test = array(
  'name' => "test",
  'exists' => true
);

Then I easily make it an object like this:

$test = (object)$test;

Now you can test it:

echo gettype($test); // "object"
echo $test->name; // "test"
0

If you're wanting to define modules in the object literal pattern "like JavaScript", you could do something like this:

$object = (object) [
    'config' => (object) [
        'username' => 'Rob Bennet',
        'email' => 'rob@madebyhoundstooth.com'
    ],

    'hello' => function() use(&$object) {
        return "Hello " . $object->config->username . ". ";
    },

    'emailDisplay' => function() use(&$object) {
        return "Your email address is " . $object->config->email;
    },

    'init' => function($options) use(&$object) {
        $object->config = $options;
        $doUsername = $object->hello;
        $doEmail = $object->emailDisplay;
        return $doUsername() . $doEmail();
    }
];

$sayMyInfo = $object->init;

echo $sayMyInfo((object) [
    'username' => 'Logan',
        'email' => 'wolverine@xmen.com'
]);

In this type of modular scenario, I usually opt for the facade pattern, I just like writing my calls thusly:

Module::action()->item;

or

Post::get()->title;

Neither of these patterns make it easy (or even possible sometimes) for testing. But this is just proof of concept. Technically, "no" there is no Object Literal in PHP, but if you're used to JavaScript syntax (which I am more so than PHP), you can fake it and do this. As you can see, it's a lot messier in PHP than in JavaScript.

Rob Bennet
  • 477
  • 1
  • 9
  • 21
0

If the json_decode(json_encode( $array )) isn't good for you, then you can use some similar functions like these. Which one is faster, I don't know.

function deep_cast_object( $o ){
  return deep_cast_object_ref( $o );
}

function deep_cast_object_ref( & $o ){

  if( is_array( $o ))
    $o = (object)$o;

  if( is_object( $o ))
    foreach( $o as & $v )
      deep_cast_object_ref( $v );

  return $o;
}

$obj = deep_cast_object(array(
  'Fractal' => array(
    'of'    => array(
      'bad' => 'design',
    ),
  ),
));

var_dump( $obj );
biziclop
  • 14,466
  • 3
  • 49
  • 65
0

In PHP, you have ro create an instance before you can use a class. Of course you can put the instances into an array later.

pgampe
  • 4,531
  • 1
  • 20
  • 31
-1

Simple solution

$obj = json_decode('{"ape":"kwyjibo"}');
echo $obj->ape;

[output:]
kwyjibo

Then you can wrap it into a function and return your literal object

$obj = literal_object(['key1','val1','key2','val2']);
vincent thorpe
  • 171
  • 1
  • 10