tags:

views:

1461

answers:

3

This topic expands on When do/should I use __construct(), __get(), __set(), and __call() in PHP? which talks about the __construct __get and __set magic methods.

As of PHP 5.3 there is a new Magic Method called __invoke. The __invoke method is called when a script tries to call an object as a function.

Now on research I have done for this method, people liken it to the Java method .run() - see Interface Runnable.

Having thought long and hard about this I can't think of any reason why you would call $obj(); as opposed to $obj->function();

Even if you were iterating over an array of objects, you would still know the main function name that you would want to run.

So is the __invoke magic method another example of 'just because you can, doesn't mean you should' shortcut in PHP, or are there cases where this would actually be the right thing to do?

+6  A: 

I believe this functionality exists mainly to support 5.3's new closure functionality. Closures are exposed as instances of the Closure class, and are directly invokable e.g. $foo = $someClosure();. A practical benefit of __invoke() is that it becomes possible to create a standard callback type, rather than using strange combinations of strings, objects and arrays depending on whether you're referencing a function, instance method or static method.

jaz303
+6  A: 

PHP does not allow the passing of function pointers like other languages. Functions are not first class in PHP. Functions being first class mainly means that you can save a function to a variable, and pass it around and execute it at any time.

The __invoke method is a way that PHP can accommodate pseudo-first-class functions.

The __invoke method can be used to pass a class that can act as a closure or a continuation, or simply as a function that you can pass around.

A lot of functional programming relies on first class functions. Even normal imperative programming can benefit from this.

Say you had a sort routine, but wanted to support different compare functions. Well, you can have different compare classes that implement the __invoke function and pass in instances to the class to your sort function, and it doesn't even have to know the name of the function.

Really, you could always have done something like passing a class and have a function call a method, but now you can almost talk about passing a "function" instead of passing a class, although it's not as clean as in other languages.

Kekoa
i don't get it ... what exactly first class functions if not $a? $a = function ($x,$y) {return ($x<$y ? $x : $y;}; $min = array_reduce(array(1,2,3), $a);
Schnalle
oooooh! okay, sorry for mixing up anonymous/first class/lambda-style functions all the time.
Schnalle
first class functions / closures in PHP 5.3: function multiplyBy($x) { return function ($y) use ($x) { return $x*$y;};}. $mulby3 = multiplyBy(3); $twentyone = $mulby3(7); - __invoke is >5.3 too, so using __invoke as a replacement for pseudo-first-class makes not always sense.
Schnalle
Many thanks for your answer, thats cleared a few things up and provided me with a lot of reading on the subject.
Phil Carter
+1  A: 

It's a combination of two things. You've correctly identified one of them already. This is indeed just like Java's IRunnable interface, where every "runnable" object implements the same method. In Java, the method is named run; in PHP, the method is named __invoke, and you don't need to explicitly implement any particular interface type beforehand.

The second aspect is the syntactic sugar, so instead of calling $obj->__invoke(), you can skip the method name, so it appears as though you're calling the object directly: $obj().

The key part for PHP to have closures is the first one. The language needs some established method to call on a closure object to make it do its thing. The syntactic sugar is just a way to make it look less ugly, as is the case with all the "special" functions with double-underscore prefixes.

Rob Kennedy