今天遇到的个问题,

  1. 场景 class A 内部 定义了一个static function f1,
  2. 该static func  f1中实例了另一个class B
  3. f1然后使用B的实例进行setAttribute 操作,其中一个attribute值是一个匿名函数 cf1
  4. cf1依赖一个参数,该参数是 B 的实例
<?php

class A
{
    public static function testClosureScope()
    {
        $objB = (new B)->setAttr1(
            function (){
                self::otherFunc();//todo 此处需要使用当前实例化的B对象作为参数
            }
        );
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

class B
{
    public $attr1;

    /**
     * @return mixed
     */
    public function getAttr1()
    {
        return $this->attr1;
    }

    /**
     * @param mixed $attr1
     */
    public function setAttr1($attr1)
    {
        $this->attr1 = $attr1;

        return $this;
    }


}

问题所在 :上面todo 的地方需要完善,How?

1.传递 $this

<?php

class A
{
    public static function testClosureScope()
    {
        $objB = (new B)->setAttr1(
            function (){
                self::otherFunc($this);//todo 此处需要使用当前实例化的B对象作为参数
            }
        );
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

ERROR, 想法是好的,但是这个$this,是传递不过去的,原因:

  • 当前 testClosureScope 方法是static

  • 即使所在方法不是static,$this 也会自动绑定到 Class A的实例,即  Closure中 的 $this会自动bind到定义的类,不一定是调用的类

#################################################################################################

解决法

1.Closure的继承作用域变量

<?php

class A
{
    public static function testClosureScope()
    {
        $objB = (new B);

        $objB->setAttr1(
            function ()use($objB){
                self::otherFunc($objB);//todo 此处需要使用当前实例化的B对象作为参数
            }
        );

        return $objB;
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

class B
{
    public $attr1;

    /**
     * @return mixed
     */
    public function getAttr1()
    {
        return $this->attr1;
    }

    /**
     * @param mixed $attr1
     */
    public function setAttr1($attr1)
    {
        $this->attr1 = $attr1;

        return $this;
    }
}

$obj  = A::testClosureScope();

$cf = $obj->getAttr1();
$cf();//RECURSION 递归引用自己

2. Closure 的 bindTo

<?php

class A
{
    public static function testClosureScope()
    {
        $f = function (){
                self::otherFunc($this);//此处需要使用当前实例化的B对象作为参数
            };
        $objB = (new B);

        $bindF = $f->bindTo($objB);//闭包绑定至 B实例;所以上面的 $this 才会生效;注意一定要接收返回值
        $objB->setAttr1($bindF);

        return $objB;
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

class B
{
    public $attr1;

    /**
     * @return mixed
     */
    public function getAttr1()
    {
        return $this->attr1;
    }

    /**
     * @param mixed $attr1
     */
    public function setAttr1($attr1)
    {
        $this->attr1 = $attr1;

        return $this;
    }
}

$obj  = A::testClosureScope();

$cf = $obj->getAttr1();
$cf();
08-01 23:51