NoteDeep
Closure是PHP的內建类,用于实现匿名函数。
一个匿名函数就是Closure类的一个对象。
类的结构:
Closure {
/* Methods */
private __construct ( void )
public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] )
public Closure bindTo ( object $newthis [, mixed $newscope = "static" ] )
public mixed call ( object $newthis [, mixed $... ] )
public static Closure fromCallable ( callable $callable )
}

::bind方法

<?php
class A {
private static $sfoo = 1;
private $ifoo = 2;
}
$cl1 = static function() {
return A::$sfoo;
};
$cl2 = function() {
return $this->ifoo;
};

$bcl1 = Closure::bind($cl1, null, 'A');
$bcl2 = Closure::bind($cl2, new A(), 'A');
echo $bcl1(), "\n";
echo $bcl2(), "\n";
?>

// 1
// 2

php官网评论里面的一个例子,使用了Closure::bind方法,配合trait,把匿名函数存到了trait里面,实现了动态给类添加方法的效果。(匿名函数内的$this,成功和类绑定)

MetaTrait.php
<?php
trait MetaTrait
{
private $methods = array();

public function addMethod($methodName, $methodCallable)
{
if (!is_callable($methodCallable)) {
throw new InvalidArgumentException('Second param must be callable');
}
$this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
}

public function __call($methodName, array $args)
{
if (isset($this->methods[$methodName])) {
return call_user_func_array($this->methods[$methodName], $args);
}

throw RunTimeException('There is no method with the given name to call');
}

}
?>

test.php
<?php
require 'MetaTrait.php';

class HackThursday {
use MetaTrait;

private $dayOfWeek = 'Thursday';

}

$test = new HackThursday();
$test->addMethod('when', function () {
return $this->dayOfWeek;
});

echo $test->when();

?>

->bindTo方法

替换匿名函数内部的$this所指向的对象 $obj
<?php

class A {
function __construct($val) {
$this->val = $val;
}
function getClosure() {
//returns closure bound to this object and scope
return function() { return $this->val; };
}
}

$ob1 = new A(1);
$ob2 = new A(2);

$cl = $ob1->getClosure();
echo $cl(), "\n";
$cl = $cl->bindTo($ob2);
echo $cl(), "\n";
?>

// 1
// 2



评论列表

    ::bind方法
    ->bindTo方法