Today's problems,
- Scenario class A defines a static function f1.
- Another class B is exemplified in this static func f1
- f1 then uses an instance of B for setAttribute operation, where one of the attribute s is an anonymous function cf1
- cf1 depends on a parameter, which is an example of B
<?php class A { public static function testClosureScope() { $objB = (new B)->setAttr1( function (){ self::otherFunc();//todo Here you need to use the currently instantiated B object as a parameter } ); } 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; } }
Question: The above todo needs to be improved, How?
1. Delivery of $this
<?php class A { public static function testClosureScope() { $objB = (new B)->setAttr1( function (){ self::otherFunc($this);//todo Here you need to use the currently instantiated B object as a parameter } ); } public static function otherFunc(B $objB) { var_dump($objB); } }
ERROR, the idea is good, but this $this is not transferable, the reason is:
-
The current testClosureScope method is static
-
Even if the method is not static, $this will automatically bind to an instance of Class A, that is, $this in Closure will automatically bind to the class defined, not necessarily the class invoked.
#################################################################################################
Solution method
1.Closure's Inheritance Scope Variables
<?php class A { public static function testClosureScope() { $objB = (new B); $objB->setAttr1( function ()use($objB){ self::otherFunc($objB);//todo Here you need to use the currently instantiated B object as a parameter } ); 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 recursively refers to itself
2. Closure's bindTo
<?php class A { public static function testClosureScope() { $f = function (){ self::otherFunc($this);//Here you need to use the currently instantiated B object as a parameter }; $objB = (new B); $bindF = $f->bindTo($objB);//Closure is bound to instance B; so the $this above will take effect; be careful to receive the return value $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();