Вы не можете вызвать обратные вызовы, добавив ()
. Это работает только в PHP 5.3 с лямбда-функциями и объектами, которые реализуют магию __invoke
(см. Также внутренний обработчик объекта get_closure
).
Во-первых, несмотря на то, что вы говорите, это не работает:
<?php
class Example {
private static $_callbacks;
private static function do_foo() { echo "foo"; }
private static function do_bar() { echo "bar"; }
public static function do_callbacks() {
self::$_callbacks['foo'] = array('Example','do_foo');
self::$_callbacks['bar'] = array('Example','do_bar');
self::$_callbacks['foo']();
self::$_callbacks['bar']();
}
}
Example::do_callbacks();
Но это не сработало бы, если бы self::$_callbacks['foo']
была лямбда-выражением:
<?php
class Example {
private static $_callbacks;
public static function do_callbacks() {
self::$_callbacks['foo'] = function () { echo "foo"; };
self::$_callbacks['foo']();
}
}
Example::do_callbacks();
Причина в парсере. Вышеуказанное компилируется в:
Class Example:
Function do_callbacks:
(...)
number of ops: 16
compiled vars: !0 = $_callbacks
line # * op fetch ext return operands
---------------------------------------------------------------------------------
6 0 > EXT_NOP
7 1 EXT_STMT
2 ZEND_FETCH_CLASS
3 ZEND_DECLARE_LAMBDA_FUNCTION '%00%7Bclosure%7D%2Ftmp%2Fcp9aicow0xb7fcd09b'
4 FETCH_W static member $2 '_callbacks'
5 ZEND_ASSIGN_DIM $2, 'foo'
6 ZEND_OP_DATA ~3, $4
9 7 EXT_STMT
8 FETCH_DIM_R $5 !0, 'foo'
9 ZEND_FETCH_CLASS
10 ZEND_INIT_STATIC_METHOD_CALL $6, $5
11 EXT_FCALL_BEGIN
12 DO_FCALL_BY_NAME 0
13 EXT_FCALL_END
10 14 EXT_STMT
15 > RETURN null
Никогда не происходит выборка статического члена (кроме назначения лямбды). Фактически, PHP компилирует переменную $_callbacks
, которая оказывается не существующей во время выполнения; отсюда твоя ошибка. Я допускаю, что это, возможно, не ошибка, но, по крайней мере, угловой случай парсера. Сначала он оценивает часть $_callbacks['foo']
, а затем пытается вызвать статическую функцию, имя которой является результатом этой оценки.
В сумме - придерживайтесь call_user_func
или forward_static_call
.