Como os retornos de chamada são escritos em PHP?
Como os retornos de chamada são escritos em PHP?
Respostas:
O manual usa os termos "retorno de chamada" e "retornável" de forma intercambiável, no entanto, "retorno de chamada" tradicionalmente se refere a um valor de cadeia ou matriz que age como um ponteiro de função , referenciando um método de função ou classe para invocação futura. Isso permitiu alguns elementos de programação funcional desde o PHP 4. Os sabores são:
$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 é uma maneira segura de usar valores de chamada em geral:
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);
}
As versões modernas do PHP permitem que os três primeiros formatos acima sejam chamados diretamente como $cb()
. call_user_func
e call_user_func_array
apoiar todos os itens acima.
Veja: http://php.net/manual/en/language.types.callable.php
Notas / Advertências:
['Vendor\Package\Foo', 'method']
call_user_func
não suporta passando não-objetos por referência, para que você pode usar call_user_func_array
ou, em versões do PHP mais tarde, guarde o retorno a um var e utilizar a sintaxe direta: $cb()
;__invoke()
método (incluindo funções anônimas) se enquadram na categoria "solicitável" e podem ser usados da mesma maneira, mas pessoalmente não os associo ao termo "retorno de chamada" herdado.create_function()
cria uma função global e retorna seu nome. É um invólucro para eval()
e funções anônimas devem ser usadas.'someGlobalFunction'
realmente é uma função definida.
Com o PHP 5.3, agora você pode fazer o seguinte:
function doIt($callback) { $callback(); }
doIt(function() {
// this will be done
});
Finalmente, uma boa maneira de fazê-lo. Um ótimo complemento para o PHP, porque os retornos de chamada são impressionantes.
A implementação de um retorno de chamada é feita assim
// 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');
Exibe: Os dados são: estes são meus dados
call_user_func()
Quando possuem uma sintaxe que lhes permite chamar dinamicamente funções e fazer retornos de chamada. Eu concordo com você!
Um truque bacana que eu descobri recentemente é usar o PHP create_function()
para criar uma função anônima / lambda para uso único. É útil para funções PHP, como array_map()
, preg_replace_callback()
, ou usort()
que as chamadas de retorno de uso para processamento personalizado. Parece muito com um eval()
arquivo oculto, mas ainda é uma boa maneira de usar o PHP em estilo funcional.
create_function()
?
bem ... com 5.3 no horizonte, tudo ficará melhor, porque com 5.3, teremos fechamentos e com eles funções anônimas
Você deseja verificar se a sua chamada é válida. Por exemplo, no caso de uma função específica, você deseja verificar e ver se a função existe:
function doIt($callback) {
if(function_exists($callback)) {
$callback();
} else {
// some error handling
}
}
is_callable( $callback )
create_function
não funcionou para mim dentro de uma classe. Eu tive 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!" );
}
}
}
Então, 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] Adicionado um parêntese ausente. Além disso, adicionei a declaração de retorno de chamada, prefiro assim.
Eu me encolho toda vez que uso create_function()
em php.
Parâmetros são uma string separada por coma, todo o corpo da função em uma string ... Argh ... Eu acho que eles não poderiam ter tornado a coisa mais feia, mesmo que tentassem.
Infelizmente, é a única opção ao criar uma função nomeada que não vale a pena.
create_function()
agora está obsoleto e não deve ser usado.
Para aqueles que não se importam em quebrar a compatibilidade com o PHP < 5.4
, sugiro usar dicas de tipo para tornar uma implementação mais limpa.
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()
foi descontinuado a partir do PHP 7.2.0. Confiar nessa função é altamente desencorajado.