我试图了解我可以在多大程度上使用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()
,我能够在功能上重现此基本功能。
基本上,我想知道的是......使用对象实例,这种功能是否可行?
答案 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
的方法和属性。这对您来说可能是也可能不是问题。