开发者

PHP5: Callbacks between Class Objects

I am trying to understand how far I can go with PHP5's closures/callbacks, but I am currently trapped in a glass case of "why doesn't this work".

In the following example, I understand that the use of $this in a callback (especially when the scope changes) isn't going to work, it's just there 开发者_开发技巧to show you how I hope to be able to use callbacks/closures.

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();

I have been able to reproduce this basic functionally by implementing Salesman as a static class and setting the callback function as Salesman::greet_customer instead of $this->greet_customer().

Basically, what I want to know is... using object instances, is this kind of functionality possible?


In php, call_user_func can accept a two-element array to call a method on a class. So if you do this:

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

it will do what you want. Another alternative on PHP 5.3.0 or greater is to use a closure along with a local copy of $this:

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


I have some good news, and some bad news.

The good news is that the next major release of PHP (5.4?) will permit anonymous functions to be properties of a class, and be callable without jumping through hoops, and will allow you to reference $this by binding the function to a specific context.

The bad news is that nobody seems to know when the PHP trunk will be turned into a release.

Now, given that you can't actually reference $this inside the anonymous function, what you can do here is very limited. One option would be to pass the current object to the function:

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

While this will work, and allow you to poke at the object from the function, you'd be limited to methods and properties labeled public. This may or may not be an issue for you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜