Astuce La fonction __invoke()

Utilisation

Parmi les méthodes magiques disponibles en PHP, la méthode __invoke() permet de "transformer un objet en fonction".

Ainsi, voici l'exemple donné dans la documentation :

<?php
class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

Ce qui affiche :

int(5)
bool(true)

Explication :

On peut appeler l'instance de notre classe comme une fonction. C'est alors la méthode __invoke() qui est exécutée.

Utilité

Dans certains languages, comme le javascript, les fonctions sont des Objets. On appelle ce principe "first-class". C'est parfois utile d'avoir une fonction sous forme d'objet à manipuler. Selon telle ou telle propriété, elle pourra s'exécuter de manières différentes.

Voici un cas d'usage proposé sur stackoverflow.com :

Imaginons qu'on veuille trier ce tableau :

$arr = [
    ['key' => 3, 'value' => 10, 'weight' => 100],
    ['key' => 5, 'value' => 10, 'weight' => 50],
    ['key' => 2, 'value' => 3, 'weight' => 0],
    ['key' => 4, 'value' => 2, 'weight' => 400],
    ['key' => 1, 'value' => 9, 'weight' => 150]
];

Via la fonction usort(), on peut trier facilement en fonction de la clé value :

$comparisonFn = function($a, $b) {
    return $a['value'] < $b['value'] ? -1 : ($a['value'] > $b['value'] ? 1 : 0);
};
usort($arr, $comparisonFn);

Maintenant si on souhaite trier en fonction de la clé weight :

usort($arr, function($a, $b) {
    return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : 0);
});

La logique de la fonction est exactement la même que précédemment, mais on ne peut pas la réutiliser. À la place, on peut créer une classe avec la méthode __invoke() :

class Comparator {
    protected $key;

    public function __construct($key) {
        $this->key = $key;
    }

    public function __invoke($a, $b) {
        return $a[$this->key] < $b[$this->key]  ? -1 : ($a[$this->key] > $b[$this->key] ? 1 : 0);
    }
}

et ainsi choisir au moment de l'appel :

usort($arr, new Comparator('key')); // tri par 'key'
usort($arr, new Comparator('value')); // tri par 'value'
usort($arr, new Comparator('weight')); // tri par 'weight'

Source : stackoverflow.com