匿名函数中私有 class 方法的范围

the scope of private class methods in an anonymous function

下面的代码没有按预期工作,更准确的注释在下面的代码

class A1 {
    function __call($name, $arguments)    {
        throw new \Exception('Method ..... ' . $name . ' not exists ...');
    }

    /* When this method is public - it works good*/
    private function test($d) {
        var_dump($d);
    }

    public function test1() {
        /* duplicate for using in anonym function */
        $_this=$this;

        #$_this->test(1); #- it works good!!!
        #var_dump($_this);

        /* create anonym func, wherein the method is called test() */
        $rrr= function()use($_this){
            #var_dump($_this); # - values of output equally with above used var_dump
            $_this->test(1); # - it do NOT WORK !!!!
        };

        $rrr();  # catch Exception of __call() ...
    }
}

$r = new A1;
var_dump($r->test1());

我不明白为什么匿名函数调用算作从外部调用,而 $this 没有改变...

错误?

因为class在编译的时候不存在$this(只有当它被实例化的时候)所以不能通过use传递;您必须在 运行 时将 $this 绑定到您的闭包:

class A1 {
    function __call($name, $arguments)    {
        throw new \Exception('Method ..... ' . $name . ' not exists ...');
    }

    /* When this method is public - it works good*/
    private function test($d) {
        var_dump($d);
    }

    public function test1() {
        /* create anonym func, wherein the method is called test() */
        $rrr= function(){
            $this->test(1);
        };
        Closure::bind($rrr, $this);
        $rrr();  # catch Exception of __call() ...
    }
}

$r = new A1;
$r->test1();

Demo

或将其作为 运行 时间参数而不是 use 参数传递:

class A1 {
    function __call($name, $arguments)    {
        throw new \Exception('Method ..... ' . $name . ' not exists ...');
    }

    /* When this method is public - it works good*/
    private function test($d) {
        var_dump($d);
    }

    public function test1() {
        /* create anonym func, wherein the method is called test() */
        $rrr= function($this){
            $this->test(1);
        };
        $rrr();  # catch Exception of __call() ...
    }
}

$r = new A1;
$r->test1();

Demo