關閉繫結和範圍

讓我們考慮這個例子:

<?php

$myClosure = function() {
    echo $this->property;
};

class MyClass
{
    public $property;

    public function __construct($propertyValue)
    {
        $this->property = $propertyValue;
    }
}

$myInstance = new MyClass('Hello world!');
$myBoundClosure = $myClosure->bindTo($myInstance);

$myBoundClosure(); // Shows "Hello world!"

嘗試將 property 的可見性更改為 protectedprivate。你收到致命錯誤,表明你無權訪問此屬性。實際上,即使閉包已繫結到物件,呼叫閉包的範圍也不是獲得該閉包所需的範圍。這就是 bindTo 的第二個論點。

如果它是 private,則訪問屬性的唯一方法是從允許它的範圍訪問它,即。類的範圍。在前面的程式碼示例中,尚未指定作用域,這意味著已在與建立閉包的位置相同的作用域中呼叫閉包。讓我們改變一下:

<?php

$myClosure = function() {
    echo $this->property;
};

class MyClass
{
    private $property; // $property is now private

    public function __construct($propertyValue)
    {
        $this->property = $propertyValue;
    }
}

$myInstance = new MyClass('Hello world!');
$myBoundClosure = $myClosure->bindTo($myInstance, MyClass::class);

$myBoundClosure(); // Shows "Hello world!"

如上所述,如果未使用此第二個引數,則在與建立閉包的位置相同的上下文中呼叫閉包。例如,在物件上下文中呼叫的方法類中建立的閉包將具有與方法相同的範圍:

<?php

class MyClass
{
    private $property;

    public function __construct($propertyValue)
    {
        $this->property = $propertyValue;
    }

    public function getDisplayer()
      {
        return function() {
              echo $this->property;
        };
      }
}

$myInstance = new MyClass('Hello world!');

$displayer = $myInstance->getDisplayer();
$displayer(); // Shows "Hello world!"