php中,给类的属性/方法赋值一个 匿名函数之后,如何调用执行?

php代码如下:

class bird{
    public function __construct($str){
        echo "bird __con <br>".$str;
    }
}

$eagle=new bird('fly');

//给类的属性/方法赋值一个 匿名函数之后
$eagle->onWorkerStart = function($str){
    var_dump($str);
    $chicken=new bird('egg');
    $chicken->onMessage = function($buffer){
        out_f($buffer); //执行外部定义的方法会不会报错?
    };
};

$eagle->onWorkerStart();  //这样会报错
($eagle->onWorkerStart)();  //这样也会报错



function out_f($buffer){
    echo "out_f".$buffer;
}

问题一:$eagle->onWorkerStart 如何执行???
问题二:$chicken->onMessage里面执行外部定义的方法out_f($buffer)会不会报错?

阅读 119
评论
    1 个回答
    • 11.1k

    问题一

    用这种方式构建的匿名 onWorkerStart 实际上会成为一个 Closure 对象, 因此你需要调用 Closure 对象的 call 方法 (此处 PHP 应该是参考了 Javascript)

    $eagle->onWorkerStart->call($eagle, 'hello'); // 'hello' 为 onWorkerStart 函数的参数

    详见 https://www.php.net/manual/zh/class.closure.php

    不过个人并不建议你这么做, 对代码可读性伤害很大. 哪怕在 Bird 类里面分别 public 声明下 onWorkerStartonMessage 也会好很多. 并进一步可以用 phpdoc 标示一下它们的类型为 Closure, 现代IDE 可以识别这个语法并根据对应类型提供语法提示.

    class bird{
        
        /**
         * @var \Closure
         */
        public onWorkerStart;
        
        /**
         * @var \Closure
         */
        public onMessage;
        
        /*.....*/
    }

    当然 PHP 7.4 以上可以直接声明类型:

    class bird{
     
        public \Closure onWorkerStart;
        
        public \Closure onMessage;
        
        /*.....*/
    }

    问题二:
    不会, 函数是全局作用域的

      撰写回答

      登录后参与交流、获取后续更新提醒