如何在 PHP 中实现回调?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:19:05  来源:igfitidea点击:

How do I implement a callback in PHP?

php

提问by Nick Stinemates

How are callbacks written in PHP?

回调是如何用 PHP 编写的?

采纳答案by Steve Clay

The manual uses the terms "callback" and "callable" interchangeably, however, "callback" traditionally refers to a string or array value that acts like a function pointer, referencing a function or class method for future invocation. This has allowed some elements of functional programming since PHP 4. The flavors are:

该手册交替使用术语“回调”和“可调用”,但是,“回调”传统上是指字符串或数组值,其作用类似于函数指针,引用函数或类方法以供将来调用。自 PHP 4 以来,这允许函数式编程的一些元素。 风格是:

$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');

This is a safe way to use callable values in 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);
}

Modern PHP versions allow the first three formats above to be invoked directly as $cb(). call_user_funcand call_user_func_arraysupport all the above.

现代 PHP 版本允许将上述前三种格式直接调用为$cb(). call_user_funccall_user_func_array支持以上所有内容。

See: http://php.net/manual/en/language.types.callable.php

请参阅:http: //php.net/manual/en/language.types.callable.php

Notes/Caveats:

注意事项/警告:

  1. If the function/class is namespaced, the string must contain the fully-qualified name. E.g. ['Vendor\Package\Foo', 'method']
  2. call_user_funcdoes not support passing non-objects by reference, so you can either use call_user_func_arrayor, in later PHP versions, save the callback to a var and use the direct syntax: $cb();
  3. Objects with an __invoke()method (including anonymous functions) fall under the category "callable" and can be used the same way, but I personally don't associate these with the legacy "callback" term.
  4. The legacy create_function()creates a global function and returns its name. It's a wrapper for eval()and anonymous functions should be used instead.
  1. 如果函数/类是命名空间的,则字符串必须包含完全限定名称。例如['Vendor\Package\Foo', 'method']
  2. call_user_func不支持通过引用传递非对象,所以您可以使用call_user_func_array,或者在以后的PHP版本,保存回调到var和使用直接的语法:$cb();
  3. 具有__invoke()方法的对象(包括匿名函数)属于“可调用”类别,可以以相同的方式使用,但我个人不会将这些与遗留的“回调”术语联系起来。
  4. 遗留create_function()创建一个全局函数并返回其名称。它是一个包装器,eval()应该改用匿名函数。

回答by Bart van Heukelom

With PHP 5.3, you can now do this:

使用 PHP 5.3,您现在可以执行以下操作:

function doIt($callback) { $callback(); }

doIt(function() {
    // this will be done
});

Finally a nice way to do it. A great addition to PHP, because callbacks are awesome.

终于有一个很好的方法来做到这一点。对 PHP 的一个很好的补充,因为回调很棒。

回答by Nick Stinemates

Implementation of a callback is done like so

回调的实现是这样完成的

// 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');

Displays: Data is: this is my data

显示:数据是:这是我的数据

回答by yukondude

One nifty trick that I've recently found is to use PHP's create_function()to create an anonymous/lambda function for one-shot use. It's useful for PHP functions like array_map(), preg_replace_callback(), or usort()that use callbacks for custom processing. It looks pretty much like it does an eval()under the covers, but it's still a nice functional-style way to use PHP.

我最近发现的一个绝妙技巧是使用 PHPcreate_function()创建一个匿名/ lambda 函数以供一次性使用。它是PHP函数等是有用的array_map()preg_replace_callback()usort()用于加工定制是使用回调。它看起来很像eval()在幕后工作,但它仍然是使用 PHP 的一种很好的函数式方式。

回答by pilif

well... with 5.3 on the horizon, all will be better, because with 5.3, we'll get closures and with them anonymous functions

好吧……随着 5.3 的到来,一切都会好起来的,因为在 5.3 中,我们将得到闭包和匿名函数

http://wiki.php.net/rfc/closures

http://wiki.php.net/rfc/closures

回答by SeanDowney

You will want to verify whatever your calling is valid. For example, in the case of a specific function, you will want to check and see if the function exists:

您将需要验证您的调用是否有效。例如,对于特定函数,您需要检查该函数是否存在:

function doIt($callback) {
    if(function_exists($callback)) {
        $callback();
    } else {
        // some error handling
    }
}

回答by goliatone

create_functiondid not work for me inside a class. I had to use call_user_func.

create_function在课堂上对我不起作用。我不得不使用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!" );
        }
    }

}

Then, to use:

然后,使用:

<?php 
include_once('Dispatcher.php');
$d = new Dispatcher( 'do_callback' );
$d->asynchronous_method();

function do_callback( $data ){
   print 'Data is: ' .  $data .  "\n";
}
?>

[Edit] Added a missing parenthesis. Also, added the callback declaration, I prefer it that way.

[编辑] 添加了一个缺少的括号。另外,添加了回调声明,我更喜欢那样。

回答by Pat

I cringe every time I use create_function()in php.

每次我create_function()在 php 中使用时我都会畏缩。

Parameters are a coma separated string, the whole function body in a string... Argh... I think they could not have made it uglier even if they tried.

参数是一个逗号分隔的字符串,整个函数体在一个字符串中......啊......我认为即使他们尝试过也不会让它变得更丑。

Unfortunately, it is the only choice when creating a named function is not worth the trouble.

不幸的是,当创建命名函数不值得麻烦时,它是唯一的选择。

回答by Kendall Hopkins

For those who don't care about breaking compatibility with PHP < 5.4, I'd suggest using type hinting to make a cleaner implementation.

对于那些不关心破坏与 PHP 兼容性的人< 5.4,我建议使用类型提示来进行更清晰的实现。

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"