All Glory to __invoke

Lost in the shiny new features (see: namespaces and closures) PHP 5.3 also added the __invoke method. While not plainly apparent, it is secretly an amazingly useful 'magic method' .

If you're not taking advantage of __invoke, you should be. Why? It provides a uniform execution points for objects that have a doPrimaryAction() style method.

What do I mean by this? Many simple, single responsibility objects have a usage that goes something like:

Instantiate

Set Options

Execute

[Optional] GOTO 2

They are essentially glorified functions with manageable defaults.

So instead of

<?php

public function add($left = 0, $right = 0) {
return $left + $right;
}

echo add(1, 2); // 3
echo add(3, 2); // 5

We have something like

<?php

class Add {
public $left;
public $right;

public function construct($left = 0, $right = 0) {
$this->left = $left;
$this->right = $right;
}

public function doMath() {
return $this->left + $this->right;
}
}

$adder = new Add;

$adder->left = 1;
$adder->right = 2;
echo $adder->doMath(); // 3

$adder->left = 3;
echo $adder->doMath(); // 5

The example is farcical and stands to illustrate my point. Everything except the doMath() method is setup for the doMath method. You are setting up the environment for doMath to execute.

This pattern of object with one primary action has a downside over a function. You need to know the class name and the invoking method name, which varies from object to object. This dear reader is where __invoke comes in.

__invoke is a magic method allowing us to treat our object as a function or more correctly a closure. It will pass the Callable type hint when added, and makes the object directly invokable via call_user_function.

What this gives us most importantly though is a uniform way across differently intentioned objects to invoke its primary action.

If we update the previous example:

<?php

class Add {
public $left;
public $right;

public function construct($left = 0, $right = 0) {
$this->left = $left;
$this->right = $right;
}

public function __invoke() {
return $this->left + $this->right;
}
}

$adder = new Add;

$adder->left = 1;
$adder->right = 2;
echo $adder(); // 3

$adder->left = 3;
echo $adder(); // 5

You can see the difference in use is slight, but the benefit is the lack of ->doMath. We know this object does one thing, now we have a uniform way to make our objects do that one thing.

I haven't seen a lot of traction with this in the community yet but I remain quite hopeful for this to pick up. I do know however that Aura appears to be a fan of the pattern, with Aura.Dispatcher using it beautifully.

Aura.Dispatcher - Aura's Dispatcher has one primary purpose - to dispatch. As such, it is a perfect use case for being invokable.