PHP 中 bind 和 bindTo 的使用

最近在看 Laravel 的源码,发现里面好多匿名函数,然后使用 bind 和 bindTo 进行绑定,调用。所以,详细了解一下 匿名函数的中的 bind 和 bindTo 还是有必要的。


匿名函数

匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数。最经常用作回调函数参数的值。如:

echo preg_replace_callback('~-([a-z])~', function ($match) 
{
    return strtoupper($match[1]);
}, 'hello-world');


也可以直接将一个匿名函数赋值给变量,如:

$fun = function($match = '') 
{
    // 函数体
};  // 特别注意,这儿一定要有 ; 结束

// 使用
$fun("abc");


匿名函数都是 Closure 类的子类,如:

var_dump($fun instanceof Closure); // bool(true)


而 Closure 类有两个方法,即 bind 和 bindTo

Closure {
    // 复制一个闭包,绑定指定的$this对象和类作用域。
    public static bind (Closure $closure , object $newthis [, mixed $newscope = 'static']): Closure
    
    // 复制当前闭包对象,绑定指定的$this对象和类作用域。
    public bindTo (object $newthis [, mixed $newscope = 'static']): Closure
}


bind 方法

先创建一个类,用于复制

class Demo
{
    private $a;
    public  $b;

    public static  $c = 100;
    private static $d = 90;

    public function __construct()
    {
        $this->a = 1;
        $this->b = 2;
    }
}

$demo = new Demo();


1、当第 2 个参数,是一个对象时,表示 闭包 里的 $this 指定的是当前对象, 如:

$fun = function() {
    var_dump($this->b);
};

$fun_bind = Closure::bind($fun, $demo);
$fun_bind(); // int(2)


如果不传第 3 个参数, 或 第 3 个参数传 'static' 表示,表示 作用域 同 $demo 相同,即不能使用 类的私有方法,如:

$fun = function() {
    var_dump($this->a);   // 会出错,因为 $a 是一个 private 属性
};

$fun_bind = Closure::bind($fun, $demo);
$fun_bind();


如果传第 3 个参数,是一个对象,或类名,表示 作用域 为 内部调用,可以调用私有方法,如:

$fun = function() {
    var_dump($this->a);
};

$fun_bind = Closure::bind($fun, $demo, $demo);
// 也可以传类名
// $fun_bind = Closure::bind($fun, $demo, Demo::class);

$fun_bind(); // int(1)


2、当第 2 个参数是 NULL 时,表示闭包只能使用 static ,不能使用 $this,如:

$fun = function() {
    // var_dump($this->a);  // 会出错,不能使用 $this
    var_dump(static::$c);
};

$fun_bind = Closure::bind($fun, NULL, Demo::class);
$fun_bind();


当第 2 个参数为 NULL 时,第 3 个参数必需要传,因为,不传的话,找不到要复制的对象, 如:

$fun = function() {
    var_dump(static::$c);
};

$fun_bind = Closure::bind($fun, NULL); // 会错,因为闭包里的 static::$c 指的是哪个类??
$fun_bind();


bindTo 方法

同 bind 一样,如:

$fun_bind = $fun->bindTo($demo);
$fun_bind();

$fun_bind = $fun->bindTo($demo, Demo::class);
$fun_bind();

$fun_bind = $fun->bindTo(NULL, Demo::class);
$fun_bind();


未经允许不得转载:易读小屋  »  PHP 中 bind 和 bindTo 的使用