5 ms·
Closure Object Binding in PHP 5.4
- deweller 15y agoI think it is worth noting here that PHP 5.4 is still in at version beta1. I'm looking forward to this new feature, as it is cumbersome to pass anonymous functions to object instances in 5.3.
- mgkimsal 15y agoWould have preferred something to enable more visually pleasing metaprogramming, like: $closure = function() { echo $this->foo; }; $context = new \StdClass; $context->foo = "Hello World"; $context->closure = $closure; $context->closure(); Not sure if this will be possible in 5.4, but haven't seen anything on it. Right now, we have to do $context->closure = $closure; $temp = $context->closure; $temp(); which is kinda ugly.
- deweller 15y agoYou can use this: call_user_func($context->closure); But yeah, some syntactic sugar would sure be nice. I'd like to see this in a future version of PHP... ($context->closure)();
- mgkimsal 15y agoIt doesn't even have to be 'sugar' like that. $content->closure() It could look at the registered methods, then scan for properties of that name that would be closures, then fall back to __call. You could add this to __call with __set() checks for assigned values being closures, but it's rather ugly to have to do that for all class definitions.
- shaunxcode 15y agoI am aware of the gnarliness of the following BUT You could do something like: class Object { public function __call($method, $args) { if(isset($this->$method) && $this->$method instanceof \Closure) { $this->$method->bindTo($this); return call_user_func_array($this->$method, $args); } } } $context = new Object; $context->foo = "Hello World"; $context->closure = function() { echo $this->foo; }; $context->closure(); Once traits are in the language (5.5?) that could just be mixed in.
- yuri41 15y agoIf you look at the RFC (https://wiki.php.net/rfc/closures/object-extension https://wiki.php.net/rfc/closures/object-extension) it's in there. But it ain't present in the current builds of 5.4, AFAIK. Don't know what's happened there...
- Udo 15y agoIt's definitely nice that closures are real objects, but I don't see the justification for the bindTo() method. Take this, for example (from the article): $app->get('/', function() use ($app) { $request = $app['request']; }); The use keyword is good for importing anything from the current context into the closure. However, I'm not sure it's a good idea in this case because it seems unnecessary - which makes the example a bit of a straw man: The $app object already knows about itself, so why not do the simpler and more loosely bound version: $app->get('/', function($app) { $request = $app['request']; }); then when calling the closure, the object just has to do this: $closure($this); That way you don't have to remember to "use ($app)" every time you define a closure (and I'm also not wild about overlapping variable names from different contexts). Now we have the new bindTo() method which results in yet more extra code: $boundClosure = $closure->bindTo($context); Granted, you could define a general bindTo mechanism once per class implementation, and being able to use $this inside the closure is nice, but I'm not sure this justifies an addition to the language's complexity when a perfectly fine method has been around that does the same thing (and with less code).
- maratd 15y ago> but I don't see the justification for the bindTo() method. The new array syntax, closures, binding ... I'm surprised you're not seeing the pattern. All of these features are borrowed from JavaScript. Absolutely fine by me. I already spend most of my time in JavaScript anyway. I'm willing to bet I'm not alone, hence the changes.
- Udo 15y agoSo it's desirable to eventually converge PHP and JavaScript? You're right: I don't get it. Why then have PHP at all? I'm not saying that retrofitting a language is a bad idea per se, I just don't see the appeal of doing it when there was a perfectly fine alternative to begin with. The new array syntax is great, and introducing closures was way overdue, but this one..? Oh well, it's in there now, so I guess there is no point of discussing it. But I do believe, on a more general note, that saying "no" to features is important - and bindTo() would have been an excellent point to say no to. For better or worse, PHP is not JavaScript and vice versa. Their paradigms are not really compatible to begin with. Transplanting stuff from one to the other just because it saves 7 bytes in developers' brains is not enough of a reason to do that in my opinion.
- dahlia 15y agoIt’s an evil thing originated from JavaScript. PHP always has borrowed evil things from other languages. As a result, PHP keeps getting more evil by the version.