$cb"/>

如何在PHP中实现回调?

如何在PHP中实现回调?

How do I implement a callback in PHP?

回调如何用PHP编写?


该手册可互换地使用术语"回调"和"可调用",但是,"回调"传统上是指充当函数指针的字符串或数组值,引用函数或类方法以供将来调用。自PHP 4以来,已经允许使用函数式编程的某些元素。

1
2
3
4
5
6
7
8
9
10
11
$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');

通常,这是使用可调用值的安全方法:

1
2
3
4
5
6
7
8
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);
}

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

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

注释/注意事项:

  • 如果函数/类已命名空间,则字符串必须包含标准名称。例如。 ['Vendor\Package\Foo', 'method']
  • call_user_func不支持通过引用传递非对象,因此您可以使用call_user_func_array,或者在更高的PHP版本中,将回调保存到var并使用直接语法:$cb();
  • 具有__invoke()方法的对象(包括匿名函数)属于"可调用"类别,并且可以按相同方式使用,但是我个人不将其与旧式"回调"术语相关联。
  • 旧版create_function()创建一个全局函数并返回其名称。它是eval()的包装,应改用匿名函数。

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

    1
    2
    3
    4
    5
    function doIt($callback) { $callback(); }

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

    最后,这是一个不错的方法。对PHP的重要补充,因为回调很棒。


    回调的实现是这样完成的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 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 . "
    "
    ;
    }


    // Call doIt() and pass our sample callback function's name.
    doIt('myCallback');

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


    我最近发现的一个妙招是使用PHP的create_function()创建用于一次使用的匿名/ lambda函数。对于使用回调进行自定义处理的PHP函数(如array_map()preg_replace_callback()usort())很有用。看起来很像是在幕后做eval(),但这仍然是使用PHP的一种不错的功能风格方式。


    您将要验证您的通话是否有效。例如,对于特定功能,您将需要检查并查看该功能是否存在:

    1
    2
    3
    4
    5
    6
    7
    function doIt($callback) {
        if(function_exists($callback)) {
            $callback();
        } else {
            // some error handling
        }
    }

    好吧……随着5.3的出现,一切都会变得更好,因为有了5.3,我们将获得闭包,并获得匿名函数

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


    create_function在课堂上对我不起作用。我不得不使用call_user_func

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?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!" );
            }
        }

    }

    然后,使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    include_once('Dispatcher.php');
    $d = new Dispatcher( 'do_callback' );
    $d->asynchronous_method();

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

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


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

    参数是一个用逗号分隔的字符串,整个函数体都在一个字符串中...哎呀...我认为即使尝试,它们也无法使其更难看。

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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"

    推荐阅读

      浏览器调用linux命令?

      浏览器调用linux命令?,系统,信息,人工智能,软件,数据,首次,地址,代码,咨询,

      py调用linux的命令?

      py调用linux的命令?,系统,代码,状态,环境,标准,工具,命令,文件,脚本,终端,lin

      linux系统命令调用?

      linux系统命令调用?,系统,单位,工具,工作,管理,地址,权威,密码,电脑,信息,怎

      脚本调用linux命令?

      脚本调用linux命令?,代码,系统,工作,底部,脚本,位置,环境,行用,官网,标准,typ

      调用函数命令linux?

      调用函数命令linux?,系统,管理,网络,通用,统一,观察,地址,代码,设备,地方,怎

      linux内核总调用命令?

      linux内核总调用命令?,工作,地址,系统,信息,管理,策略,命令,目录,时间,基础,

      linux编程调用命令?

      linux编程调用命令?,系统,标准,管理,工作,基础知识,情况,环境,设备,基础,首

      linux命令窗口调用?

      linux命令窗口调用?,系统,工具,首页,终端,命令,数据,盘中,代码,密码,快捷键,

      linux服务器调用命令?

      linux服务器调用命令?,系统,地址,设备,标准,工作,密码,中心,盘中,网络,软件,

      linuxc调用命令框?

      linuxc调用命令框?,系统,工作,标准,情况,设备,环境,命令,函数,语言,程序,如何

      linux查询函数命令?

      linux查询函数命令?,系统,信息,名称,标准,函数,百度,代码,名字,最新,实时,Lin

      linux系统调用命令行?

      linux系统调用命令行?,系统,网络,代码,密码,位置,工作,通用,平台,电脑,环境,

      批量调用linux命令?

      批量调用linux命令?,工具,下来,软件,系统,密码,地址,时间,认证,向日葵,文件,l

      linux内核调用命令?

      linux内核调用命令?,系统,工作,信息,工具,内核,命令,名称,标准,流程,网络,在l

      linux内核态调用命令?

      linux内核态调用命令?,系统,密码,名称,代码,状态,异常,内核,工作,服务,数据,

      linux命令调用记录?

      linux命令调用记录?,信息,系统,名称,地址,时间,数据,命令,服务,环境,用户,lin

      linux调用编辑命令行?

      linux调用编辑命令行?,工作,状态,系统,命令,模式,数字,代码,首开,第一,管理,l

      Python有哪些常用函数?

      Python有哪些常用函数?,数据,函数,地址,数字,培训,工作,网络,位置,字符串,字