Ссылка на статический метод в PHP?
В 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 - меняется ли ответ в зависимости от версии?)
Ответы
Ответ 1
PHP обрабатывает обратные вызовы как строки, а не указатели на функции. Причина, по которой ваш первый тест работает, заключается в том, что интерпретатор PHP предполагает foo1 как строку. Если вы допустили ошибку уровня E_NOTICE, вы должны убедиться в этом.
"Использование undefined константы 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();
Ответ 2
В 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();
?>
Ответ 3
Вы можете использовать полное имя статического метода, включая пространство имен.
<?php
function foo($method)
{
return $method('argument');
}
foo('YourClass::staticMethod');
foo('Namespace\YourClass::staticMethod');
Массив имен array('YourClass', 'staticMethod')
равен ему. Но я думаю, что строка может быть более понятной для чтения.
Ответ 4
В 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);
?>
Ответ 5
Кажется, это работает для меня:
<?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();
?>
Ответ 6
В дополнение к тому, что было сказано, вы также можете использовать возможности отражения 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');
}
}
Ответ 7
Исходя из фона 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');
Это функция, которая возвращает функцию, вызывающую функцию, которую вы хотите вызвать. Звучит странно, но, как вы можете видеть на практике, это кусок пирога.
Работа с пространствами имен и возвращаемая функция должны работать так же, как и статический метод - параметры работают одинаково.
Ответ 8
"Элемент или метод, объявленный со статикой, не может быть доступен с переменной, являющейся экземпляром объекта и не может быть переопределен в расширяющемся классе
(http://theserverpages.com/php/manual/en/language.oop5.static.php)