【问题标题】:Reference to static method in PHP?引用 PHP 中的静态方法?
【发布时间】:2008-10-10 16:20:15
【问题描述】:

在 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 ——答案是否也因版本而异?)

【问题讨论】:

    标签: php syntax


    【解决方案1】:

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

    【讨论】:

    • 谢谢,call_user_func 成功了。我注意到,如果函数被传递给另一个类中的方法,那么,并非不自然,它需要使用“Bar”而不是“self”来限定范围。
    • "PHP 将回调处理为字符串,而不是函数指针。"这正是我想要的
    【解决方案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') 等于它。但我认为字符串可能更易于阅读。

      【讨论】:

      • ...奇怪,根据“使用”规范无法解决。我需要从 symfony 类型类实体类型的 query_builder 上的控制器传递一个静态方法。
      【解决方案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】:

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

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

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

        【讨论】:

          【解决方案6】:

          这似乎对我有用:

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

          【讨论】:

          • 您只是在调用 Calc(),而不是先将其存储在变量中。将函数分配给变量并传递它们对于编写通用算法很有用,例如接受不同比较函数进行排序的排序函数。
          【解决方案7】:

          除了上面所说的,你还可以使用 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');
              }
          
          }
          

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

            • 这意味着你不能使用“$this->”调用静态方法,这并不意味着你不能在一个(有效的函数值)中传递静态方法变量。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-01
            • 1970-01-01
            • 2011-01-07
            • 2015-02-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多