Vou vincular outra pergunta a essa, porque eu estava tentando encerrar.
akinuri
Respostas:
173
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_funce call_user_func_arrayapoiar todos os itens acima.
Se a função / classe estiver com namespace, a sequência deverá conter o nome completo. Por exemplo['Vendor\Package\Foo', 'method']
call_user_funcnão suporta passando não-objetos por referência, para que você pode usar call_user_func_arrayou, em versões do PHP mais tarde, guarde o retorno a um var e utilizar a sintaxe direta: $cb();
Objetos com um __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.
O legado create_function()cria uma função global e retorna seu nome. É um invólucro para eval()e funções anônimas devem ser usadas.
De fato, o uso da função é a maneira correta de fazê-lo. Ao usar uma variável e depois chamá-la, como sugerido na resposta aceita, é legal, é feio e não se adapta bem ao código.
Icco 30/08/09
4
Resposta aceita alterada. Concordo com os comentários, esta é uma ótima resposta.
9609 Nick Stinemates
Seria útil para os leitores provenientes da programação Python apontar na resposta que 'someGlobalFunction'realmente é uma função definida.
TMOTTM
1
No PHP 5.3, existem encerramentos, veja a resposta de Bart van Heukelom . É muito mais simples e "padrão" do que toda essa bagunça herdada.
reallynice
Sim, mencionei funções anônimas na minha resposta, mas o OP solicitou "retorno de chamada" (em 2008) e esses retornos de chamada no estilo antigo ainda são muito utilizados em toneladas de bases de código PHP.
23415 Steve
74
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');
Existem algumas outras maneiras de fazer isso, como mostrado acima. Eu realmente pensei o mesmo.
Nick Stinemates
3
@ Nick Retallack, não vejo o que há de tão horrível nisso. Para os idiomas que eu conheço, como JavaScript e C #, todos eles podem estruturar sua função de retorno de chamada nesse padrão. Vindo de JavaScirpt e C #, eu realmente não estou acostumado a call_user_func (). Isso me faz sentir que tenho que me adaptar ao PHP, e não o contrário.
Antony
4
@Antony Eu estava objetando ao fato de que strings são indicadores de função nessa linguagem. Eu publiquei esse comentário há três anos, por isso estou bastante acostumado a ele agora, mas acho que o PHP é a única linguagem que conheço (além do shell scripting) onde esse é o caso.
Nick Retallack
1
@Antony Prefiro usar a mesma sintaxe que uso em javascript. Então, eu nem entendo por que as pessoas querem usar call_user_func()Quando possuem uma sintaxe que lhes permite chamar dinamicamente funções e fazer retornos de chamada. Eu concordo com você!
precisa saber é o seguinte
9
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.
Infelizmente, o coletor de lixo não funciona muito bem com essa construção produzindo possíveis vazamentos de memória. Se você quer desempenho, evite a função create_function ().
Fuxia
1
Ai. Obrigado pelo aviso.
yukondude
Você se importaria de atualizar a resposta com a versão do PHP 7.4 (funções de seta) e adicionar um aviso sobre obsoleto create_function()?
Dharman
7
bem ... com 5.3 no horizonte, tudo ficará melhor, porque com 5.3, teremos fechamentos e com eles funções anônimas
E se o retorno de chamada não for uma função, mas uma matriz que contenha objeto e método?
precisa
3
ou melhor #is_callable( $callback )
Roko C. Buljan 30/03
1
Ambas são boas sugestões - Será necessário verificar sua própria implementação específica de como você faz um retorno de chamada. Eu esperava advertir contra chamar algo que não existia causando uma morte fatal. Eu fiz a resposta mais geral
SeanDowney
5
create_functionnão funcionou para mim dentro de uma classe. Eu tive que usar call_user_func.
A classe Dispatcher não requer um atributo para que $ this-> callback = $ callback funcione?
James P.
@ Poulson James: PHP é uma linguagem dinâmica, por isso funciona. Mas eu estava sendo preguiçoso. Eu geralmente declaro propriedades, facilita a vida de todos. Sua pergunta me fez olhar para esse código novamente e detectar um erro de sintaxe, tu. Obrigado
goliatone
Eu não sabia que isso era possível. Obrigado pela resposta :).
James P.
Não seria mais seguro declarar a função do_callback antes de criar o objeto Dispatcher e chamar o método assíncrono?
ejectamenta
3
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.
E, é claro, é a avaliação de sequência de tempo de execução, para que não seja verificada a sintaxe válida ou qualquer outra coisa em tempo de compilação.
21139 hobbs
Esta resposta está desatualizada nos últimos 2 anos. create_function()agora está obsoleto e não deve ser usado.
Dharman 01/03
2
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 hintreturn $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"
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:
Esta é uma maneira segura de usar valores de chamada em geral:
As versões modernas do PHP permitem que os três primeiros formatos acima sejam chamados diretamente como
$cb()
.call_user_func
ecall_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 usarcall_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 paraeval()
e funções anônimas devem ser usadas.fonte
'someGlobalFunction'
realmente é uma função definida.Com o PHP 5.3, agora você pode fazer o seguinte:
Finalmente, uma boa maneira de fazê-lo. Um ótimo complemento para o PHP, porque os retornos de chamada são impressionantes.
fonte
A implementação de um retorno de chamada é feita assim
Exibe: Os dados são: estes são meus dados
fonte
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, comoarray_map()
,preg_replace_callback()
, ouusort()
que as chamadas de retorno de uso para processamento personalizado. Parece muito com umeval()
arquivo oculto, mas ainda é uma boa maneira de usar o PHP em estilo funcional.fonte
create_function()
?bem ... com 5.3 no horizonte, tudo ficará melhor, porque com 5.3, teremos fechamentos e com eles funções anônimas
http://wiki.php.net/rfc/closures
fonte
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:
fonte
is_callable( $callback )
create_function
não funcionou para mim dentro de uma classe. Eu tive que usarcall_user_func
.Então, para usar:
[Editar] Adicionado um parêntese ausente. Além disso, adicionei a declaração de retorno de chamada, prefiro assim.
fonte
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.
fonte
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.fonte
create_function()
foi descontinuado a partir do PHP 7.2.0. Confiar nessa função é altamente desencorajado.