Javascript object literals look like this
[js]
var a = {
'var_1' : 'Hello' ,
'var_2' : 'World' ,
'get' : function()
{
alert(a.var_1);
}
};
[/js]
As similar thing can be done in PHP using anonymous functions (since 5.3)
Quick example
$a = [ 'var_1' => 'Hello World' , 'happy' => function() use(&$a) { echo $a['var_1']; } ]; $a['happy'](); //outputs Hello World
Looks interesting ? Ofcourse! Since version 5.3 Php added support for closures and that feature has been used above to create javascript style object literals.
The use(&$a) expression makes the variable $a available inside the function happy.
Adding more properties
$a = [ 'var_1' => 'Hello World' , 'happy' => function() use(&$a) { echo $a['var_1']; } ]; $a['happy'](); //add more properties, both variables and functions $a['song'] = 'Ring a Roses'; $a['sing'] = function() use(&$a) { echo $a['song']; }; $a['sing']();
More properties can be added initial declaration.
The object literals shown above are singletons. They cannot be copied and since their is no class, its not possible to create another object of same structure, without writing it again of course.
Wrapping in a function can help
function get_object() { $a = [ 'var_1' => 'Hello World' , 'happy' => function() use(&$a) { echo $a['var_1']; } ]; return $a; } $k = get_object(); $k2 = get_object(); $k['happy'](); $k2['happy'] = function() use(&$k) { echo "Happier"; }; $k2['happy']();
The function get_object acts like a constructor creating objects (literals).
Object style syntax
The syntax used so far is like that of associative arrays. The neater object style syntax can also be used.
$a = (object) [ 'var_1' => 'Hello World' , 'happy' => function() use(&$a) { echo $a->var_1; } ]; //this will not work //$a->happy(); //but this will work $b = $a->happy; $b();
The above has a small drawback. That $a->happy() makes php complain that happy is not a function of object $a. So the same property has to be assigned to another variable and then that variable is used to call the function.
There is an alternative to make it work. Using the __call magic method. But that would ofcourse need a proper class. Lets take an example
class js_object { function __call($name, $args) { if (is_callable($this->$name)) { //call the function return call_user_func_array($this->$name, $args); } } } $a = new js_object; //add properties $a->song = 'Ring a Roses'; $a->sing = function() use(&$a) { echo $a->song; }; $a->sing(); //Output Ring a Roses
These can be cloned as well
class js_object { function __call($name, $args) { if (is_callable($this->$name)) { //call the function return call_user_func_array($this->$name, $args); } } } $a = new js_object; //add properties $a->song = 'Ring a Roses'; $a->sing = function() use(&$a) { echo $a->song; }; $a->sing(); //Output Ring a Roses $b = clone $a; $b->sing = function() use(&$b) { echo 'I am a clone'; }; $b->sing();
It would be nice if __call was passing $self (as the reference to $this) as a first argument (exactly like in class definitions in Python).
I’ve done something like this, You can check it on my Github: https://github.com/radmen/ProtoClass/blob/master/ProtoClass.php
yes, thats a good idea.
I believe you mean PHP 5.4
the same would work in php 5.3 as well, just the array declaration syntax needs to be changed.
Array literal syntax does not work in php 5.3
supermac:~ Josh$ php -v
PHP 5.3.13 with Suhosin-Patch (cli) (built: Jun 20 2012 17:05:20)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
supermac:~ Josh$ php -r ‘$a = [“h” => “i”];’
Parse error: parse error in Command line code on line 1
you need php 5.4 or change the array syntax from […] to array(…)
cool article, thanks!
You say “The object literals are singletons. They cannot be copied and since their is no class”.
Would it not be possible to use PHP’s “clone” keyword for this?
Just a thought. :-)
clone can be used when creating objects with a class, like js_object.
clone cannot be used with arrays.