В PHP я могу использовать нормальную функцию как переменную без проблем, но я не понял, как использовать статический метод. Я просто пропустил правильный синтаксис, или это невозможно?
(EDIT: первый предложенный ответ, похоже, не работает. Я расширил свой пример, чтобы показать возвращенные ошибки.)
function foo1($a,$b) { return $a/$b; } class Bar { static function foo2($a,$b) { return $a/$b; } public function UseReferences() { // WORKS FINE: $fn = foo1; print $fn(1,1); // WORKS FINE: print self::foo2(2,1); print Bar::foo2(3,1); // DOES NOT WORK ... error: Undefined class constant 'foo2' //$fn = self::foo2; //print $fn(4,1); // DOES NOT WORK ... error: Call to undefined function self::foo2() //$fn = 'self::foo2'; //print $fn(5,1); // DOES NOT WORK ... error: Call to undefined function Bar::foo2() //$fn = 'Bar::foo2'; //print $fn(5,1); } } $x = new Bar(); $x->UseReferences();
(Я использую PHP v5.2.6 – меняется ли ответ в зависимости от версии?)
PHP обрабатывает обратные вызовы как строки, а не указатели на функции. Причина, по которой ваш первый тест работает, заключается в том, что интерпретатор PHP предполагает foo1 как строку. Если вы допустили ошибку уровня E_NOTICE, вы должны убедиться в этом.
«Использование неопределенного константы foo1 – предполагается« foo1 »»
К сожалению, вы не можете вызвать статические методы. Область (класс) релевантна, поэтому вам нужно использовать call_user_func.
<?php function foo1($a,$b) { return $a/$b; } class Bar { public static function foo2($a,$b) { return $a/$b; } public function UseReferences() { $fn = 'foo1'; echo $fn(6,3); $fn = array( 'self', 'foo2' ); print call_user_func( $fn, 6, 2 ); } } $b = new Bar; $b->UseReferences();
В php 5.2 вы можете использовать переменную как имя метода в статическом вызове, но для использования переменной в качестве имени класса вам придется использовать обратные вызовы, как описано BaileyP.
Однако из php 5.3 вы можете использовать переменную как имя класса в статическом вызове. Так:
class Bar { public static function foo2($a,$b) { return $a/$b; } public function UseReferences() { $method = 'foo2'; print Bar::$method(6,2); // works in php 5.2.6 $class = 'Bar'; print $class::$method(6,2); // works in php 5.3 } } $b = new Bar; $b->UseReferences(); ?>
Вы можете использовать полное имя статического метода, включая пространство имен.
<?php function foo($method) { return $method('argument'); } foo('YourClass::staticMethod'); foo('Namespace\YourClass::staticMethod');
Массив array('YourClass', 'staticMethod')
имен array('YourClass', 'staticMethod')
равен ему. Но я думаю, что строка может быть более понятной для чтения.
В PHP 5.3.0 вы также можете сделать следующее:
<?php class Foo { static function Bar($a, $b) { if ($a == $b) return 0; return ($a < $b) ? -1 : 1; } function RBar($a, $b) { if ($a == $b) return 0; return ($a < $b) ? 1 : -1; } } $vals = array(3,2,6,4,1); $cmpFunc = array('Foo', 'Bar'); usort($vals, $cmpFunc); // This would also work: $fooInstance = new Foo(); $cmpFunc = array('fooInstance', 'RBar'); // Or // $cmpFunc = array('fooInstance', 'Bar'); usort($vals, $cmpFunc); ?>
Кажется, это работает для меня:
<?php class Foo{ static function Calc($x,$y){ return $x + $y; } public function Test(){ $z = self::Calc(3,4); echo("z = ".$z); } } $foo = new Foo(); $foo->Test(); ?>
В дополнение к тому, что было сказано, вы также можете использовать возможности отражения PHP:
class Bar { public static function foo($foo, $bar) { return $foo . ' ' . $bar; } public function useReferences () { $method = new ReflectionMethod($this, 'foo'); // Note NULL as the first argument for a static call $result = $method->invoke(NULL, '123', 'xyz'); } }
Исходя из фона javascript и испорченного им, я просто закодировал это:
function staticFunctionReference($name) { return function() use ($name) { $className = strstr($name, '::', true); if (class_exists(__NAMESPACE__."\\$className")) $name = __NAMESPACE__."\\$name"; return call_user_func_array($name, func_get_args()); }; }
Чтобы использовать его:
$foo = staticFunctionReference('Foo::bar'); $foo('some', 'parameters');
Это функция, которая возвращает функцию, вызывающую функцию, которую вы хотите вызвать. Звучит необычно, но, как вы можете видеть на практике, это кусок пирога.
Работа с пространствами имен и возвращаемой функцией должна работать так же, как и статический метод – параметры работают одинаково.
«Элемент или метод, объявленный со статикой, не может быть доступен с переменной, которая является экземпляром объекта и не может быть переопределена в расширяющемся классе»
( http://theserverpages.com/php/manual/en/language.oop5.static.php )