php Closure $this做用域问题

今天遇到的个问题,php

  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,是传递不过去的,缘由:this

  • 当前 testClosureScope 方法是staticcode

  • 即便所在方法不是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 的 bindToget

<?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();
相关文章
相关标签/搜索