Aus*_*yde 5 php static callback
最近在我正在开发的项目中,我需要将回调存储在静态成员数组中,如下所示:
class Example {
private static $_callbacks = array(
'foo'=>array('Example','do_foo'),
'bar'=>array('Example','do_bar')
);
private static function do_foo() { }
private static function do_bar() { }
}
Run Code Online (Sandbox Code Playgroud)
为了调用它们,我尝试了明显的(甚至是天真的)语法(在Example
类中):
public static function do_callbacks() {
self::$_callbacks['foo']();
self::$_callbacks['bar']();
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,这不起作用,导致我正在访问一个未定义的变量的通知,以及一个致命错误,指出self::$_callbacks['foo']
需要可调用.
然后,我试过call_user_func
:
public static function do_callbacks() {
call_user_func(self::$_callbacks['foo']);
call_user_func(self::$_callbacks['bar']);
}
Run Code Online (Sandbox Code Playgroud)
它奏效了!
我的问题是:
为什么我需要call_user_func
用作中间人,而不是直接打电话给他们?
您不能通过附加 来调用回调()
。这只适用于 PHP 5.3,带有 lambda 函数和实现__invoke
魔法的对象(另请参阅内部get_closure
对象处理程序)。
首先,不管你怎么说,这都行不通:
\n\n<?php\nclass Example {\n private static $_callbacks;\n private static function do_foo() { echo "foo"; }\n private static function do_bar() { echo "bar"; }\n\n public static function do_callbacks() {\n self::$_callbacks[\'foo\'] = array(\'Example\',\'do_foo\');\n self::$_callbacks[\'bar\'] = array(\'Example\',\'do_bar\');\n\n self::$_callbacks[\'foo\']();\n self::$_callbacks[\'bar\']();\n }\n}\nExample::do_callbacks();\n
Run Code Online (Sandbox Code Playgroud)\n\nself::$_callbacks[\'foo\']
但如果是 lambda,它甚至无法工作:
<?php\nclass Example {\n private static $_callbacks;\n\n public static function do_callbacks() {\n self::$_callbacks[\'foo\'] = function () { echo "foo"; };\n\n self::$_callbacks[\'foo\']();\n }\n}\n\nExample::do_callbacks();\n
Run Code Online (Sandbox Code Playgroud)\n\n原因在于解析器。以上编译为:
\n\n\n类示例:\n函数 do_callbacks:\n(...)\n操作数: 16\n编译变量: !0 = $_callbacks\nline # * op fetch ext return operands\n--------- -------------------------------------------------- ----------------------\n 6 0 > EXT_NOP \n 7 1 EXT_STMT \n 2 ZEND_FETCH_CLASS \n 3 ZEND_DECLARE_LAMBDA_FUNCTION \'%00%7Bclosure%7D% 2Ftmp%2Fcp9aicow0xb7fcd09b\'\n 4 FETCH_W 静态成员 $2 \'_callbacks\'\n 5 ZEND_ASSIGN_DIM $2, \'foo\'\n 6 ZEND_OP_DATA ~3, $4\n 9 7 EXT_STMT \n 8 FETCH_DIM_R $5 !0, \ 'foo\'\n 9 ZEND_FETCH_CLASS \n 10 ZEND_INIT_STATIC_METHOD_CALL $6, $5\n 11 EXT_FCALL_BEGIN \n 12 DO_FCALL_BY_NAME 0 \n 13 EXT_FCALL_END \n 10 14 EXT_STMT \n 15 > RETURN null\n\n\n
永远不会获取静态成员(除了 lambda 的赋值)。事实上,PHP 编译了一个变量$_callbacks
,结果在运行时并不存在;因此你的错误。我承认这可能不是一个错误,但至少是解析器的一个极端情况。它首先评估该$_callbacks[\'foo\']
部分,然后尝试调用其名称由该评估产生的静态函数。
总之 \xe2\x80\x93 坚持call_user_func
or forward_static_call
。