PHP5:类对象之间的回调

时间:2011-03-06 05:52:35

标签: php oop closures

我试图了解我可以在多大程度上使用PHP5的闭包/回调,但我目前陷入了“为什么不能正常工作”的案例。

在下面的示例中,我了解在回调中使用$this(特别是在范围更改时)不起作用,它只是向您展示我希望如何能够使用回调/闭包。

class Customer {
  public $name = '';
  public $callback = NULL;

  function __construct($name) {
    $this->name = $name;
  }
  function when_enters($callback) {
    $this->callback = $callback;
  }
  function enter_store() {
    if(is_callable($this->callback))
      call_user_func($this->callback);
  }
}

class Salesman {
  public $customer = NULL;

  function add_customer(&$customer) { 
    $this->customer =& $customer;
    $this->customer->when_enters(function() {
      $this->greet_customer();
    });
  }
  function greet_customer() {
    echo "Hello, {$this->customer->name}!";
  }
}
$salesman = new Salesman();
$customer = new Customer('John');
$salesman->add_customer(&$customer);
$customer->enter_store();

通过将Salesman实现为静态类并将回调函数设置为Salesman::greet_customer而不是$this->greet_customer(),我能够在功能上重现此基本功能。

基本上,我想知道的是......使用对象实例,这种功能是否可行?

2 个答案:

答案 0 :(得分:3)

在php中,call_user_func可以接受一个双元素数组来调用类上的方法。所以,如果你这样做:

$this->customer->when_enters(array($this,'greet_customer'));

它会做你想要的。 PHP 5.3.0或更高版本的另一个替代方法是使用闭包以及$this的本地副本:

$this_copy=$this;
$this->customer->when_enters(function() use ($this_copy) {
    $this_copy->greet_customer();
});

答案 1 :(得分:1)

我有一些好消息,还有一些坏消息。

好消息是PHP的下一个主要版本(5.4?)将允许匿名函数成为类的属性,并且可以在不跳过循环的情况下调用, will allow you to reference $this by binding the function to a specific context

坏消息是,似乎没有人知道PHP主干何时会变成发行版。

现在,鉴于你无法在匿名函数中实际引用$this,你在这里可以做的非常有限。一种选择是将当前对象传递给函数:

function enter_store() {
  if(is_callable($this->callback))
    call_user_func($this->callback, $this);
}

虽然这会起作用,并允许您从函数中查找对象,但您将被限制为标记为public的方法和属性。这对您来说可能是也可能不是问题。