如何将$ this绑定到在PHP 5.4中作为方法参数传递的闭包?

时间:2013-12-09 10:39:53

标签: php php-5.4

有没有办法将$this绑定到作为参数传递的闭包? 我阅读并重读了我在手册或互联网上找到的所有内容,但没有人提到这种行为,除了这篇博文: http://www.christophh.net/2011/10/26/closure-object-binding-in-php-54/ 提到它但没有说明如何做到这一点。

所以这是一个例子。在调用get(function() {})方法时,我希望传递给它的回调函数绑定到对象,即绑定到$this,但遗憾的是它不起作用。我有什么方法可以做到吗?

class APP
{
    public $var = 25;

    public function __construct() {

    }
    public function get($callback) {
        if (!is_callable($callback)) {
            throw new InvalidArgumentException('Paran must be callable.');
        }
        // $callback->bindTo($this);
        $callback->bindTo($this, $this);
        $callback();
    }
}

$app = new APP();
$app->get(function() use ($app) {
    echo '<pre>';
    var_dump($app);
    echo '<br />';
    var_dump($this);
});

$app有效。 $this为NULL。

4 个答案:

答案 0 :(得分:8)

我实际上不明白为什么使用bindTo方法在这种情况下不起作用,但我可以使用Closure::bind

来使其工作
public function get($callback) {
    if (!is_callable($callback)) {
        throw new InvalidArgumentException('Param must be callable.');
    }

    $bound = Closure::bind($callback, $this);
    $bound();
}

修改

显然bindTo方法具有相同的行为,因此您应该将其返回值重新分配给$callback。例如:

public function get($callback) {
    if (!is_callable($callback)) {
        throw new InvalidArgumentException('Param must be callable.');
    }

    $callback = $callback->bindTo($this);
    $callback();
}

答案 1 :(得分:3)

这样做:

class APP
{
  public $var = 25;

  public function __construct() {}

  public function get($callback) {
    if (!is_callable($callback)) {
      throw new InvalidArgumentException('Param must be callable.');
    }
    // $callback->bindTo($this);
    // you must save result in another var and call it
    $callback1 = $callback->bindTo($this, $this);
    $callback1();
  }
}

$app = new APP();
$app->get(function() use ($app) {
  echo '<pre>';
  var_dump($app);
  echo '<br />';
  var_dump($this);
});

答案 2 :(得分:1)

将其作为参数传递:

    public function get($callback) {
        if (!is_callable($callback)) {
            throw new InvalidArgumentException('Paran must be callable.');
        }
        // $callback->bindTo($this);
        return $callback($this);
    }

...

$app = new APP();
$app->get(function($that) use ($app) {
    echo '<pre>';
    var_dump($app);
    echo '<br />';
    var_dump($that);
});

或者,如果您确实需要绑定它,则必须使用返回函数的函数,如下所示:

    public function getCallback($callback) {
        return function($app){
            return $callback($this, $app);
        }
    }

...

$app = new APP();
$f = $app->get(function($that, $app) {
    echo '<pre>';
    var_dump($app);
    echo '<br />';
    var_dump($that);
});
$f($app);

答案 3 :(得分:1)

小修正:请勿使用is_callable检查参数是否传递Closure

因为is_callable也接受名称为function的String。

public function get(\Closure $callback) {

    $bound = \Closure::bind($callback, $this);
    $bound();
}

is_callable我们有这种可能性:

$app = new App;


$app->get('my_function');

如果存在函数,则抛出此错误:

  

Closure :: bind()期望参数1为Closure,字符串为

因为&#34; My_function&#34;在is_callable的测试中通过,但Closure::bind期望Closure的实例。