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