Comment les callbacks sont-ils écrits en PHP?
Comment les callbacks sont-ils écrits en PHP?
Réponses:
Le manuel utilise les termes "callback" et "callable" de manière interchangeable, cependant, "callback" se réfère traditionnellement à une valeur de chaîne ou de tableau qui agit comme un pointeur de fonction , référençant une fonction ou une méthode de classe pour un appel futur. Cela a permis certains éléments de programmation fonctionnelle depuis PHP 4. Les saveurs sont:
$cb1 = 'someGlobalFunction';
$cb2 = ['ClassName', 'someStaticMethod'];
$cb3 = [$object, 'somePublicMethod'];
// this syntax is callable since PHP 5.2.3 but a string containing it
// cannot be called directly
$cb2 = 'ClassName::someStaticMethod';
$cb2(); // fatal error
// legacy syntax for PHP 4
$cb3 = array(&$object, 'somePublicMethod');
C'est un moyen sûr d'utiliser des valeurs appelables en général:
if (is_callable($cb2)) {
// Autoloading will be invoked to load the class "ClassName" if it's not
// yet defined, and PHP will check that the class has a method
// "someStaticMethod". Note that is_callable() will NOT verify that the
// method can safely be executed in static context.
$returnValue = call_user_func($cb2, $arg1, $arg2);
}
Les versions modernes de PHP permettent aux trois premiers formats ci-dessus d'être appelés directement en tant que $cb()
. call_user_func
et call_user_func_array
soutenez tout ce qui précède.
Voir: http://php.net/manual/en/language.types.callable.php
Remarques / mises en garde:
['Vendor\Package\Foo', 'method']
call_user_func
ne supporte pas le passage des non-objets par référence, vous pouvez utiliser call_user_func_array
ou, dans les versions PHP plus tard, enregistrez le rappel à un var et utiliser la syntaxe directe: $cb()
;__invoke()
méthode (y compris les fonctions anonymes) entrent dans la catégorie "appelable" et peuvent être utilisés de la même manière, mais personnellement je ne les associe pas au terme "rappel" hérité.create_function()
crée une fonction globale et renvoie son nom. C'est un wrapper pour eval()
et des fonctions anonymes devraient être utilisées à la place.'someGlobalFunction'
s'agit bien d'une fonction définie.
Avec PHP 5.3, vous pouvez maintenant faire ceci:
function doIt($callback) { $callback(); }
doIt(function() {
// this will be done
});
Enfin une belle façon de le faire. Un excellent ajout à PHP, car les rappels sont géniaux.
L'implémentation d'un callback se fait comme ceci
// This function uses a callback function.
function doIt($callback)
{
$data = "this is my data";
$callback($data);
}
// This is a sample callback function for doIt().
function myCallback($data)
{
print 'Data is: ' . $data . "\n";
}
// Call doIt() and pass our sample callback function's name.
doIt('myCallback');
Affiche: Les données sont: ce sont mes données
call_user_func()
Quand ils ont une syntaxe qui leur permet d'appeler dynamiquement des fonctions et de faire des rappels. Je suis d'accord avec toi!
Une astuce astucieuse que j'ai récemment trouvée est d'utiliser PHP create_function()
pour créer une fonction anonyme / lambda pour une utilisation ponctuelle. Il est utile pour les fonctions PHP comme array_map()
, preg_replace_callback()
ou usort()
que callbacks utilisation pour le traitement personnalisé. Cela ressemble à peu près à un eval()
sous les couvertures, mais c'est toujours une belle façon fonctionnelle d'utiliser PHP.
create_function()
?
eh bien ... avec 5.3 à l'horizon, tout ira mieux, car avec 5.3, on aura des fermetures et avec elles des fonctions anonymes
Vous voudrez vérifier quel que soit votre appel est valide. Par exemple, dans le cas d'une fonction spécifique, vous voudrez vérifier et voir si la fonction existe:
function doIt($callback) {
if(function_exists($callback)) {
$callback();
} else {
// some error handling
}
}
is_callable( $callback )
create_function
n'a pas fonctionné pour moi dans une classe. Je devais utiliser call_user_func
.
<?php
class Dispatcher {
//Added explicit callback declaration.
var $callback;
public function Dispatcher( $callback ){
$this->callback = $callback;
}
public function asynchronous_method(){
//do asynch stuff, like fwrite...then, fire callback.
if ( isset( $this->callback ) ) {
if (function_exists( $this->callback )) call_user_func( $this->callback, "File done!" );
}
}
}
Ensuite, pour utiliser:
<?php
include_once('Dispatcher.php');
$d = new Dispatcher( 'do_callback' );
$d->asynchronous_method();
function do_callback( $data ){
print 'Data is: ' . $data . "\n";
}
?>
[Edit] Ajout d'une parenthèse manquante. De plus, j'ai ajouté la déclaration de rappel, je la préfère ainsi.
Je grince des dents à chaque fois que j'utilise create_function()
en php.
Les paramètres sont une chaîne séparée par des virgules, tout le corps de la fonction dans une chaîne ... Argh ... Je pense qu'ils n'auraient pas pu le rendre plus laid même s'ils avaient essayé.
Malheureusement, c'est le seul choix lorsque la création d'une fonction nommée ne vaut pas la peine.
create_function()
est désormais obsolète et ne doit pas être utilisé.
Pour ceux qui ne se soucient pas de rompre la compatibilité avec PHP < 5.4
, je suggère d'utiliser l'indication de type pour créer une implémentation plus propre.
function call_with_hello_and_append_world( callable $callback )
{
// No need to check $closure because of the type hint
return $callback( "hello" )."world";
}
function append_space( $string )
{
return $string." ";
}
$output1 = call_with_hello_and_append_world( function( $string ) { return $string." "; } );
var_dump( $output1 ); // string(11) "hello world"
$output2 = call_with_hello_and_append_world( "append_space" );
var_dump( $output2 ); // string(11) "hello world"
$old_lambda = create_function( '$string', 'return $string." ";' );
$output3 = call_with_hello_and_append_world( $old_lambda );
var_dump( $output3 ); // string(11) "hello world"
create_function()
est obsolète depuis PHP 7.2.0. Il est fortement déconseillé de se fier à cette fonction.