17/06/2011

Tour d'horizon des Callbacks en PHP

Je suis toujours étonné de voir de nombreux développeurs PHP, pourtant habitués à travailler avec des callbacks en JavaScript, connaître si peu voire pas du tout les callbacks PHP.

C'est pourquoi je vous propose aujourd'hui un petit rappel des callbacks en PHP :

Un callback, c'est quoi ? En un mot, Un callback est une référence vers un code exécutable.

L'utilisation de callbacks est très fréquente dans certains langages. Un exemple simple en JavaScript :

<a onclick="doAnything()">example</a>

La fonction doAnything() est un callback, qui sera exécuté à chaque clic sur le lien.

Création d'un callback en PHP

En PHP, les callbacks peuvent être définis de nombreuses manières :

Fonction anonyme

$callback = function() {
    echo "un callback dans une fonction anonyme";
};

Fonction existante

Les callbacks peuvent référer une fonction existante. Dans ce cas, on utilise le nom de la fonction comme callback :

$callback = 'maFonction';

Méthode de classe existante

De la même façon, on peut référer une méthode de classe, avec cette fois quelques subtilités :

$callback = array('NomDeLaClass','maMethode');

Equivaut à :

$obj = new NomDeLaClass;
$callback = array($obj,'maMethode');

Ou encore (méthode statique) :

$callback = array('NomDeLaClass::maMethodeStatique');

Cas particuliers

Pour accéder au parent de la classe actuelle, utilisez le mot clef "parent" de cette façon :

$callback = array('parent::maMethode');

et cela de la même façon pour self et static :

$callback = array('self::maMethode');
$callback = array('static::maMethode');

Appeler/Exécuter un callback

le plus simple est sans doute d'utiliser la fonction call_user_func :

call_user_func($callback);

le moins élégant (c'est le moins qu'on puisse dire :-)) est d'utiliser la syntaxe suivante :

$callback();

Passage de paramètres et références

Nous allons nous attarder maintenant sur les paramètres à passer au callback. C'est simple :

$callback($param1, $param2);
// ou
call_user_func($callback, $param1, $param2);

la fonction call_user_func a une soeur, call_user_func_array, qui permet de passer les paramètres sous forme de tableau :

call_user_func_array($callback, array($param1, $param2));

Jusque là, c'est simple. Il faut juste faire attention au passages de paramètres par référence. En effet, la fonction call_user_func() ne passe pas les paramètres par référence :

function test(&$val) {
}
call_user_func('test', $value);
// Warning: Parameter 1 to test()
// expected to be a reference, value given

Il faut ruser et passer par call_user_func_array() en forçant la référence :

function test(&$a) {
}
call_user_func_array('test',array(&$value));
// Cette fois c'est bon

Performances

Les appels de fonctions de type callback sont plus lents que des appels de fonction directs. Voici un bench sur 1 million d'itérations :

Bench Callbacks en PHP 5.3

Certes il y a une différence, mais dans application standard cette différence est généralement négligeable.

Le mot de la fin

Vous me direz que PHP n'est pas à la base un langage où l'utilisation massive des callbacks est pertinente. Mais bien utilisé, les callbacks peuvent significativement alléger le code, et en voici un exemple trivial :

$array=array('pomme','peche','poire','abricot');
array_walk($array, function(&$item) {
    $item = strtoupper($item);
});
print_r($array);
//Array
//(
//    [0] => POMME
//    [1] => PECHE
//    [2] => POIRE
//    [3] => ABRICOT
//)

Et vous, vous avez l'habitude d'utiliser des callbacks, ou bien vous réservez ça pour d'autres langages ?

Pochette du livre Qualité logicielle pour les développeurs

Si ce blog vous plaît, vous trouverez de nombreux conseils pratiques dans mon livre. C'est une bonne manière de me soutenir et de m'encourager

Qualité logicielle pour les développeurs

Le livre qui vous aide à améliorer la qualité de vos projets.

  • ✅ Comment mettre en place des tests automatisés pérennes ;
  • ✅ Comment analyser la qualité de votre code ;
  • ✅ Faites adhérer votre équipe à la qualité logicielle.
blog comments powered by Disqus

© Jean-François Lépine, 2013 - 2024