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对象和类作用域的闭包给你使用.

讲解几种情况

  • 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,通过第三个参数传入带命名空间的类名。

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

例子

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是对象方式调用,闭包函数是从另外一个对象中获取的,然后在绑定到其他对象上。

03-30 19:36