PHP 闭包传递给对象方法时无法访问 $this

Can't access $this on PHP Closure passed to an object method

我正在尝试传递一个使用对象数据的闭包,而不必将对象分配给变量并将其作为参数传递给闭包,但我似乎无法找出正确的方法它。

这是我的任意class代码:

class Person
{
    var $__data = [];

    function setData($key, $value)
    {
        $this->__data[$key] = $value;
        return $this;
    }

    function setAutoData($map)
    {
        $this->__data = array_merge($this->__data, $map());
        return $this;
    }

    function getData($key)
    {
        return $this->__data[$key];
    }

}

这里的这段代码 可以工作 并将 first_name 添加到数据数组:

$p = (new Person())->setData('full_name', 'Valerie Maddison Bricks');

print_r($p->setAutoData(function () use($p) {
    return [
        'first_name' => array_shift(explode(' ', $p->getData('full_name')))
    ];
}));

/*
Output:

Person Object
(
    [__data] => Array
        (
            [full_name] => Valerie Maddison Bricks
            [first_name] => Valerie
        )

)
*/

这个不起作用

print_r((new Person())
            ->setData('full_name', 'Valerie Maddison Bricks')
            ->setAutoData(function () {
                return [
                    'first_name' => array_shift(explode(' ', $this->getData('full_name'))),
                ];
            }));

/*
Output:
Fatal error:  Uncaught Error: Using $this when not in object context in C:\Damian\xampp\web\dbo-dev\teste.php:44
Stack trace:
#0 C:\Damian\xampp\web\dbo-dev\teste.php(22): {closure}()
#1 C:\Damian\xampp\web\dbo-dev\teste.php(46): Person->setAutoData(Object(Closure))
#2 {main}
  thrown in C:\Damian\xampp\web\dbo-dev\teste.php on line 44
*/

有没有办法以类似的方式不依赖变量来实现?

为了避免使用$p,可以在闭包的调用中传入$this。但是你不能在匿名函数中使用$this

$this->__data = array_merge($this->__data, $map($this));

然后,

->setAutoData(function ($object) {
    $array = explode(' ', $object->getData('full_name'));
    return [
        'first_name' => array_shift($array),
    ];
})

请注意 array_shift 需要引用。您应该为此创建一个变量。

代码:

class Person
{
    private $__data = [];

    public function setData($key, $value)
    {
        $this->__data[$key] = $value;
        return $this;
    }

    public function setAutoData($map)
    {
        $this->__data = array_merge($this->__data, $map($this));
        return $this;
    }

    public function getData($key)
    {
        return $this->__data[$key];
    }

}

print_r(
    (new Person())
    ->setData('full_name', 'Valerie Maddison Bricks')
    ->setAutoData(function ($object) {
        $array = explode(' ', $object->getData('full_name'));
        return [
            'first_name' => array_shift($array),
        ];
    })
);

输出:

Person Object
(
    [__data:Person:private] => Array
        (
            [full_name] => Valerie Maddison Bricks
            [first_name] => Valerie
        )

)