在"匿名"对象中使用$ this

sub*_*nid 3 php anonymous-class

我使用以下类来模仿PHP中的匿名对象:

class AnonymousObject
{
    protected $methods = array();

    public function __construct(array $options) {
        $this->methods = $options;
    }

    public function __call($name, $arguments) {
        $callable = null;
        if (array_key_exists($name, $this->methods))
            $callable = $this->methods[$name];
        elseif(isset($this->$name))
            $callable = $this->$name;

        if (!is_callable($callable))
            throw new BadMethodCallException("Method {$name} does not exist");

        return call_user_func_array($callable, $arguments);
    }
}
Run Code Online (Sandbox Code Playgroud)

(https://gist.github.com/Mihailoff/3700483)

现在,只要声明的函数代表它们自己一切正常,但每当我尝试从另一个函数调用这样的函数时......

$anonymous = new AnonymousObject(array(
    "foo" => function() { $this->bar(); }, 
    "bar" => function() { } 
));
Run Code Online (Sandbox Code Playgroud)

然后我当然得到了 Fatal error: Using $this when not in object context

有没有办法解决这个问题?

Vol*_*erK 5

您可以使用表示匿名函数的Closure实例的bind()或bindTo()方法.

<?php
class AnonymousObject
{
    protected $methods = array();

    public function __construct(array $options) {
        $this->methods = $options;
    }

    public function __call($name, $arguments) {
        $callable = null;
        if (array_key_exists($name, $this->methods))
            $callable = $this->methods[$name];
        elseif(isset($this->$name))
            $callable = $this->$name;

        if (!is_callable($callable))
            throw new BadMethodCallException("Method {$name} does not exists");

        $callable = $callable->bindTo($this);
        return call_user_func_array($callable, $arguments);
    }
}

$anonymous = new AnonymousObject(array(
    "foo" => function() { echo 'foo'; $this->bar(); }, 
    "bar" => function() { echo 'bar'; } 
));

$anonymous->foo();
Run Code Online (Sandbox Code Playgroud)

(例子不太正确,因为它只适用于匿名函数;不适用于所有其他callable()替代品,例如$ this-> name部分)

打印foobar.