关闭绑定和范围

让我们考虑这个例子:

<?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!"