在PHP中引用静态方法?

时间:2008-10-10 16:20:16

标签: php syntax

在PHP中,我可以使用普通函数作为变量而没有问题,但我还没有弄清楚如何使用静态方法。我只是错过了正确的语法,或者这是不可能的?

(编辑:第一个建议的答案似乎不起作用。我已扩展我的示例以显示返回的错误。)

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 - 答案会根据版本而改变吗?)

8 个答案:

答案 0 :(得分:28)

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();

答案 1 :(得分:9)

在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();
?>

答案 2 :(得分:4)

您可以使用静态方法的全名,包括命名空间。

<?php
    function foo($method)
    {
        return $method('argument');
    }

    foo('YourClass::staticMethod');
    foo('Namespace\YourClass::staticMethod');

名称数组array('YourClass', 'staticMethod')等于它。但我认为字符串可能更清晰,可供阅读。

答案 3 :(得分:1)

在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);

?>

答案 4 :(得分:0)

这似乎对我有用:

<?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();

?>

答案 5 :(得分:0)

除了上述内容之外,您还可以使用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');
    }

}

答案 6 :(得分:0)

来自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');

这是一个函数,它返回一个调用你想要调用的函数的函数。听起来很花哨,但正如你在实践中所看到的那样,这是一块蛋糕。

使用命名空间,返回的函数应该像静态方法一样工作 - 参数的工作方式相同。

答案 7 :(得分:-3)

“使用static声明的成员或方法不能使用作为对象实例的变量访问,并且不能在扩展类中重新定义”

http://theserverpages.com/php/manual/en/language.oop5.static.php