在现有类对象中声明PHP匿名函数

3

可能是重复问题:
使用匿名函数初始化类属性

我已经编写了相当长时间的PHP程序,而PHP 5.3的匿名函数是在构建一些简单脚本时帮助你很多的东西之一。然而,我不明白为什么以下示例不起作用?

$db         = new PDO([..]);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->die    = function($str){ die(var_dump( $str )); };

$db->die('[..]');

毕竟,我所做的就是在PDO实例的“->die”属性上声明匿名函数。这让我觉得这可能是PHP的一个bug。

发生了什么?new PDO([..])代表什么? - Pekka
它将简单地产生“致命错误:在[..]的第[..]行中调用未定义的方法PDO :: die()”。 - Gajus
3个回答

1
将函数分配给属性不会将属性更改为函数。要执行存储在属性中的函数,必须使用__call魔术方法:
class Foo extends PDO {
    function __call($function, $args) {
        return call_user_func_array($this->{$function}, $args);
    }
}

$db         = new Foo([..]);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->die    = function($str){ die(var_dump( $str )); };

$db->die('[..]');

0

这个有效:

class Foo{
    public $bar;
}
$foo = new Foo;
$foo->bar = function(){
    echo "Hello, world\n";
};
call_user_func($foo->bar);

你可以将call_user_func替换为$func = $foo->bar; $func(); - petraszd

0
根据这个问题的答案:在实例中设置匿名函数

这是设计上的问题(或者说是设计错误)。那里提供了一些解决方法建议。

那是另一种情况。我在实例初始化之后声明匿名函数。没有明显的失败原因。 - Gajus
哦,没错。第二个链接中的答案应该适用于任何情况吧? - Pekka
你是指__call()的“解决方法”吗?那需要扩展原始类,通常破坏了匿名函数的概念。 - Gajus
@Guy 不,我指的是 call_user_func_array() 解决方法,无论您是否扩展了原始类都应该适用。虽然这远非优雅。这可以被视为设计缺陷,但我认为除了向 PHP 开发人员抱怨并要求在未来版本中修复它之外,没有什么可以做的了。 - Pekka
无论如何,我会让这个答案保持活跃几个小时,看看是否有人能提供更合理的解释。 - Gajus
@Guy,可能的解释在于PHP的架构。尽管现在PHP中可以使用匿名函数,但是与JavaScript不同,函数在PHP中并不是一等公民。我猜想为了直接调用一个方法,该方法仍然需要在类定义中进行注册。无论如何,很有兴趣看看是否有人能够提供证据。 - Pekka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接