Use cases for __invoke()

I’ve come across some code recently that uses the __invoke() magic method, and I’m curious as to what the use cases might be for this method? Is it to allow objects to be used interchangeably with anonymous functions or something like that?

This is a good question, and I’m struggling to find a use for it as well, so I searched for a while and found this on StackOverflow
http://stackoverflow.com/questions/888064/php-5-3-magic-method-invoke

Quoted here to save people time

[quote]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.[/quote]

So taking his example, as this isn’t a technique I would think of for his example, I personally would pass in an Interface. So maybe call it ISort, which my different sorting classes implement, and therefore when I pass it into another class, it simply knows it can call $a->Sort($parm1, $parm2); and be done.

I guess the __invoke permits you to do this instead (except I have no idea if you can pass in parameters to __invoke):

$a($parm1, $parm2);

I’m not sure I see the full benefit.

The following also has an example, but again, it isn’t something I see “as necessary”…
http://www.lornajane.net/posts/2012/phps-magic-__invoke-method-and-the-callable-typehint

function sparkles(Callable $func) {
  $func();
  return "fairy dust";
}
 
class Butterfly {
  public function __invoke() {
    echo "flutter";
  }
}
 
$bob = new Butterfly();
echo sparkles($bob); // flutterfairy dust

There must be a better reason to use this that I’m not thinking of.

Okay, so the more I think about this, the more I come to the conclusion, this is really only useful when you don’t know or don’t want to know the implementation of the object you are receiving. You simply want to execute it without knowing anything about it.

1 Like

I actually find __invoke() very useful as it is very similar to C#'s delegate method. Classes with __invoke() magic methods are themselves delegates, and can be used in event driven programming.

One issue I have with PHP’s __invoke() is that if you use such object as a property on a container object, you cannot call it by using the $this->invokeobject() approach, as it generates a method not found error. This is very annoying to me, but I understand that it can be ambiguous whether you are calling a property, or a method in this case.

The following example demonstrates this issue. As you can see I’ve been advocating for a change of this behavior, but it has not been taken seriously by PHP internals.
https://bugs.php.net/bug.php?id=50029&thanks=3

Do you have any code on GitHub that is using __invoke? As I’d love to see how you implemented it.

I do not at this point, I plan to implement a plugin and scheduled task system in my still-under-development framework that will make use of __invoke() as mimic of C# delegate. I cannot show any code right now, until I actually have it, but there are some other use cases that professional PHP programmers have come out with.

Here’s one from Lorna Mitchell:
http://www.lornajane.net/posts/2012/phps-magic-__invoke-method-and-the-callable-typehint

Here’s another by Bence Eros:

And yet another by Jose Da Silva:
http://blog.josedasilva.net/revisiting-php-5-3-__invoke-magic-method/

As you can see, invokable objects can serve as the same purpose of closure as callback function. Because it’s defined in a class and depends on instance of a class, it’s actually reusable and can even support polymorphism. Of course, I may not be correct and there can be better ways to achieve this than using __invoke(), but at least it does offer a very convenient solution to some problems. In fact, if someone has better idea, I am glad to learn too, since __invoke() is a magic method after all and therefore suffers performance headache to some extent.

1 Like

Yeah that’s what I was thinking, plus they have the advantage of being able to be autoloaded, although I think i saw somewhere that autoloaded functions are coming to PHP (or did I dream it?)

Yeah, Id say you are about right. I dont use function autoloading myself though, since I do not write orphan functions without in classes, all my functions are instance methods in my framework. But for those who actually write library of functions, it will help a bit.

Also I’ve found another use case for PHP __invoke(), in which C# delegates directly translates into PHP invokable objects. I think this will also give me some more insights into how to design pseudo-delegates like C#'s in my own framework:
http://www.php-compiler.net/blog/2011/pass-delegates-into-php

So this come back to:

Right?

I’m not saying there isn’t a place for that, but that is the ideal scenario for using __invoke(), is it not? Otherwise, you could simply use interfaces to enforce a contract so you knew which method to call.

I guess I don’t write a lot of applications where I don’t want to know what I’m receiving (or don’t want to know). Granted technically, I don’t know what I’m receiving, I know the object sent to me implements the following contract (but I don’t actually know what the object is). I use interfaces a lot to setup contracts for how things should behave/executed and pass the objects that way, so I have a set “plan” that enforces their execution.

To some extent it is true, you can use __invoke() when you do not know which method to call. But I still do not think it’s the main purpose of __invoke(), or at least it’s missing the point of where the idea of __invoke() came from at the very beginning. __invoke() is designed to compensate for PHP’s lack of first class function, so by creating an invokable object, you are essentially creating a first class function. An ideal scenario of invokable object is that it consists of only a constructor and an __invoke() method in its public interface, and it’s sole responsibility is to serve a first class function. I know the approach may be strange and it only mimics first class function in some ways, but I am sure this was the original intention of __invoke(). Maybe __invoke() has been misused since most PHP applications do not need first class functions anyway, but it will indeed help at certain circumstances.

Okay, so really its intent is to permit you to use the callback options of various php functions (in the way you could if you wrote your code in a procedural manner). This simply extends the ability to do so with OO in mind.

I’m starting to see the usefulness a bit more.

The thing that prompted me to think about this is that last night I was re-reading the Kingdom of Nouns article. It seems that invokeable objects would be one way to name objects that are actions rather than ‘things’.

You are starting to get it. But honestly, I believe __invoke() makes you write code in functional manner(or at least pseudo-functional manner), not procedural manner. Maybe I am wrong, but the intention of __invoke() is to compensate for PHP’s lack of support for functional programming techniques. There’s a difference between procedural and functional.

Yes, I agree with your sediment, but there was always a gap between the functions that existed prior to OO in PHP and after once OO was introduced that can now be closed. As you couldn’t really provide a callback to a class (without a bit of hackery) before __invoke.

With that said, it looks similar to techniques Ruby utilizes and I think that would help with those who dabble in Ruby and PHP to an extent.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.