¿Cómo se escriben las devoluciones de llamada en PHP?
¿Cómo se escriben las devoluciones de llamada en PHP?
Respuestas:
El manual usa los términos "devolución de llamada" y "invocable" indistintamente, sin embargo, "devolución de llamada" se refiere tradicionalmente a una cadena o valor de matriz que actúa como un puntero de función , haciendo referencia a una función o método de clase para una futura invocación. Esto ha permitido algunos elementos de programación funcional desde PHP 4. Los sabores son:
$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');
Esta es una forma segura de usar valores invocables en general:
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);
}
Las versiones modernas de PHP permiten que los primeros tres formatos anteriores se invoquen directamente como $cb(). call_user_funcy call_user_func_arrayapoyar todo lo anterior.
Ver: http://php.net/manual/en/language.types.callable.php
Notas / Advertencias:
['Vendor\Package\Foo', 'method']call_user_funcno soporta que pasa no-objetos por referencia, por lo que puede utilizar cualquiera call_user_func_arrayo, en versiones posteriores de PHP, excepto la devolución de llamada a un var y utilizar la sintaxis directa: $cb();__invoke()método (incluidas las funciones anónimas) se incluyen en la categoría "invocable" y se pueden usar de la misma manera, pero personalmente no los asocio con el término heredado de "devolución de llamada".create_function()crea una función global y devuelve su nombre. Es un contenedor para eval()y las funciones anónimas deben usarse en su lugar.'someGlobalFunction'hecho es una función definida.
Con PHP 5.3, ahora puede hacer esto:
function doIt($callback) { $callback(); }
doIt(function() {
// this will be done
});
Finalmente una buena manera de hacerlo. Una gran adición a PHP, porque las devoluciones de llamada son impresionantes.
La implementación de una devolución de llamada se realiza así
// 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');
Muestra: Los datos son: estos son mis datos
call_user_func()cuando tienen una sintaxis que les permite llamar dinámicamente funciones y hacer devoluciones de llamada. ¡Estoy de acuerdo contigo!
Un ingenioso truco que he encontrado recientemente es usar PHP create_function()para crear una función anónima / lambda para un solo uso. Es útil para funciones PHP como array_map(), preg_replace_callback(), o usort()que el uso devoluciones de llamada para un tratamiento personalizado. Parece más o menos como lo hace eval()debajo de las cubiertas, pero sigue siendo una buena forma de estilo funcional para usar PHP.
create_function()?
bueno ... con 5.3 en el horizonte, todo será mejor, porque con 5.3, obtendremos cierres y con ellos funciones anónimas
Querrás verificar lo que sea que tu llamada sea válida. Por ejemplo, en el caso de una función específica, querrá verificar y ver si la función existe:
function doIt($callback) {
if(function_exists($callback)) {
$callback();
} else {
// some error handling
}
}
is_callable( $callback )
create_functionno funcionó para mí dentro de una clase. Tuve que usar 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!" );
}
}
}
Luego, para usar:
<?php
include_once('Dispatcher.php');
$d = new Dispatcher( 'do_callback' );
$d->asynchronous_method();
function do_callback( $data ){
print 'Data is: ' . $data . "\n";
}
?>
[Editar] Se agregó un paréntesis faltante. Además, agregó la declaración de devolución de llamada, lo prefiero de esa manera.
Me estremezco cada vez que uso create_function()en php.
Los parámetros son una cadena separada por coma, todo el cuerpo de la función en una cadena ... Argh ... Creo que no podrían haberlo hecho más feo, incluso si lo intentaran.
Desafortunadamente, es la única opción cuando no vale la pena crear una función con nombre.
create_function()ahora está en desuso y no debe usarse.
Para aquellos a quienes no les importa romper la compatibilidad con PHP < 5.4, les sugiero que utilicen sugerencias de tipo para hacer una implementación más limpia.
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() ha sido DEPRECADA a partir de PHP 7.2.0. Confiar en esta función es altamente desaconsejado.