代码之家  ›  专栏  ›  技术社区  ›  Eric

在PHP中引用静态方法?

  •  18
  • Eric  · 技术社区  · 16 年前

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

    8 回复  |  直到 16 年前
        1
  •  29
  •   Peter Bailey    16 年前

    PHP将回调处理为字符串,而不是函数指针。您的第一个测试工作的原因是PHP解释器假设 foo1 一串。如果您启用了E_通知级别错误,您应该看到这方面的证据。

    “未定义常量foo1的使用-假定为'foo1'”

    <?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
  •  10
  •   rewbs    16 年前

    在PHP5.2中,可以在静态调用中使用变量作为方法名,但要使用变量作为类名,必须使用BaileyP描述的回调。

    但是,在PHP5.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
  •  6
  •   Jiangge Zhang    9 年前

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

    <?php
        function foo($method)
        {
            return $method('argument');
        }
    
        foo('YourClass::staticMethod');
        foo('Namespace\YourClass::staticMethod');
    

    名称数组 array('YourClass', 'staticMethod') 它等于它。但我认为这条线可能更清晰。

        4
  •  1
  •   dwallace    14 年前

    在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
  •  0
  •   eddy eddy    16 年前

    这似乎对我有用:

    <?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
  •  0
  •   hek2mgl    12 年前

    除了上面所说的,您还可以使用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
  •  0
  •   Camilo Martin    11 年前

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

    它是一个函数,返回一个调用您想要调用的函数的函数。听起来很花哨,但正如你在实践中看到的,这是小菜一碟。

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