Closure::bind
Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。
其实后半句表述很不清楚。 我的理解: 把一个闭包转换为某个类的方法(只是这个方法不需要通过对象调用), 这样闭包中的$this、static、self就转换成了对应的对象或类。
创建并返回一个 匿名函数, 它与当前对象的函数体相同、绑定了同样变量,但可以绑定不同的对象,也可以绑定新的类作用域。
从我个人理解,和js里面的call函数有点类似。可以改变闭包对象指定的作用域。
简单说,就是把闭包当成对象的成员方法或者静态成员方法.
这个方法是 Closure::bindTo() 的静态版本
说明
public static Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] ) : Closure
参数
-
closure
需要绑定的匿名函数。
-
newthis
需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包。
-
newscope
想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 私有、保护方法 的可见性
返回值
返回一个新的 Closure 对象 或者在失败时返回 FALSE
理解
范例
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";
成员方法中使用$this访问对象, 静态成员方法直接使用类名::成员的方法。
但是因为返回的是匿名函数, 没有函数名, 所以返回一个已经绑定$this对象和类作用域的闭包给你使用.
返回的闭包函数,已经绑定了$this对象和类的作用域,意思就是说直接执行闭包函数,就是相当于执行的是对象方法,或者类方法
讲解几种情况
- 1、只绑定$this对象.
- 2、只绑定类作用域.
- 3、同时绑定$this对象和类作用域.(文档的说法)
- 4、都不绑定.(这样一来只是纯粹的复制, 文档说法是使用cloning代替bind或bindTo)
1.只绑定$this对象
closure = function ($name, $age) {
$this->name = $name;
$this->age = $age;
};
class Person {
public $name;
public $age;
public function say() {
echo "My name is {$this->name}, I'm {$this->age} years old.\n";
}
}
$person = new Person();
//把$closure中的$this绑定为$person
//这样在$bound_closure中设置name和age的时候实际上是设置$person的name和age
//也就是绑定了指定的$this对象($person)
$bound_closure = Closure::bind($closure, $person);
$bound_closure('php', 100);
$person->say(); //输出:My name is php, I’m 100 years old.
注意: 在上面的这个例子中,是不可以在$closure中使用static的,如果需要使用static,通过第三个参数传入带命名空间的类名。
把closure闭包函数中的 $this 绑定到一个对象,这样执行闭包函数,就相当于执行对象的方法。
相当于就是在对象中添加了成员方法,所以闭包函数内的处理也就在处理对象内数据
2、只绑定类作用域.
$closure = function ($name, $age) {
static::$name = $name;
static::$age = $age;
};
class Person {
static $name;
static $age;
public static function say()
{
echo "My name is " . static::$name . ", I'm " . static::$age. " years old.\n";
}
}
//把$closure中的static绑定为Person类
//这样在$bound_closure中设置name和age的时候实际上是设置Person的name和age
//也就是绑定了指定的static(Person)
$bound_closure = Closure::bind($closure, null, Person::class);
$bound_closure('php', 100);
Person::say(); //输出:My name is php, I’m 100 years old.
注意: 在上面的例子中,是不可以在$closure中使用$this的,因为我们的bind只绑定了类名,也就是static,如果需要使用$this,新建一个对象作为bind的第二个参数传入。
3、同时绑定$this对象和类作用域.(文档的说法)
在这个例子中可以在$closure中同时使用$this和static
$closure = function ($name, $age, $sex) {
$this->name = $name;
$this->age = $age;
static::$sex = $sex;
};
class Person {
public $name;
public $age;
static $sex;
public function say()
{
echo "My name is {$this->name}, I'm {$this->age} years old.\n";
echo "Sex: " . static::$sex . ".\n";
}
}
$person = new Person();
//把$closure中的static绑定为Person类, $this绑定为$person对象
$bound_closure = Closure::bind($closure, $person, Person::class);
$bound_closure('php', 100, 'female');
$person->say(); //输出:My name is php, I’m 100 years old. Sex: female.
4、都不绑定.(这样一来只是纯粹的复制, 文档说法是使用cloning代替bind或bindTo)
$closure = function () {
echo "bind nothing.\n";
};
//与$bound_closure = clone $closure;的效果一样
$bound_closure = Closure::bind($closure, null);
$bound_closure();//输出:bind nothing.
这个就用clone好了吧…
Closure::bindTo
Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域。
创建并返回一个 匿名函数, 它与当前对象的函数体相同、绑定了同样变量,但可以绑定不同的对象,也可以绑定新的类作用域。
“绑定的对象”决定了函数体中的 $this 的取值,“类作用域”代表一个类型、决定在这个匿名函数中能够调用哪些 私有 和 保护 的方法。 也就是说,此时 $this 可以调用的方法,与 newscope 类的成员函数是相同的。
静态闭包不能有绑定的对象( newthis 参数的值应该设为 NULL)不过仍然可以用 bubdTo 方法来改变它们的类作用域。
说明
public Closure::bindTo ( object $newthis [, mixed $newscope = 'static' ] ) : Closure``
参数
-
newthis
绑定给匿名函数的一个对象,或者 NULL 来取消绑定。
-
newscope
关联到匿名函数的类作用域,或者 'static' 保持当前状态。如果是一个对象,则使用这个对象的类型为心得类作用域。 这会决定绑定的对象的 保护、私有成员 方法的可见性。
返回值
返回新创建的 Closure 对象 或者在失败时返回 FALSE
如果你只是想要复制一个匿名函数,可以用 cloning 代替。
例子
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";
和 Closure::bind() 作用一样,只是一个是静态的调用,一个是对象的的调用。
对比 Closure::bind 和 Closure::bindTo
两者功能功能一样,不同的是匿名函数的来源不一样,Closure::bind 是静态调用,直接是闭包函数当参数传入;而Closure::bindTo是对象方式调用,闭包函数是从另外一个对象中获取的,然后在绑定到其他对象上。