在PHP中将静态函数分配给变量

6
我想将一个静态函数赋值给一个变量,以便我可以将它作为参数传递。例如:
class Foo{
    private static function privateStaticFunction($arg1,$arg2){
      //compute stuff on the args          
    }

    public static function publicStaticFunction($foo,$bar){

         //works
         $var = function(){
                   //do stuff
                };

         //also works
         $var = function($someArg,$someArg2){
                   //do stuff
         };

         //Fatal error: Undefined class constant 'privateStaticFunction'                    
         $var = self::privateStaticMethod;

         //same error
         $var = Foo::privateStaticFunction;

         //compiles, but errors when I try to run $var() somewhere else, as expected
         //Fatal error: Call to private method Foo::privateStaticMethod() from context ''
         $var = function(){
             return Foo::privateStaticMethod(); 
         }; 
    }
}

我尝试了几种变化,但都没有起作用。

我甚至不指望这种功能性黑客攻击在PHP中能够起作用,但是谁知道呢?

在PHP中是否可能做到这一点,还是我需要想出一些使用eval的黑客方法?

P.S.:##php上的LawnGnome提到使用array('Foo','privateStaticMethod')可以实现我的需求,但我不明白他的意思,而且他看起来很忙,我也没有进一步追问。

3个回答

4
您希望使用call_user_func函数并传入一个数组参数。
$var = array('Foo','privateStaticMethod');
call_user_func($var);

请注意,该方法上的“private”修饰符将使其仅在Foo类内部可调用。 call_user_func将一个可调用作为第一个参数。请注意,从PHP 5.2.3开始,您可以避免在您的情况下使用数组表示法。

通过在索引0处传递类名而不是对象,也可以传递静态类方法,而无需实例化该类的对象。从PHP 5.2.3开始,还可以传递'ClassName::methodName'。


完美的回答。然而,当试图从另一个闭包(尽管全部都在类中)中调用call_user_func时,我似乎无法访问私有方法。那是另一回事了。但是,类中的闭包应该能够看到该类的私有方法,对吧? - Felipe
据我所知,在类中定义的闭包与该类没有任何关联,因此类访问规则应与外部函数调用您的私有方法相同。但是您可以使用Closure::bindTo来解决问题。 - jimp

3
作为一条提示,你应该这样设置你的静态变量:
static $privateStaticMethod;

$var = self::$privateStaticMethod;

在使用self::时漏掉$符号将尝试访问类常量而不是变量。

实际上,我认为你想表达的这一行应该是:

//Fatal error: Undefined class constant 'privateStaticFunction'                    
$var = self::privateStaticFunction("arga", "argb");

如果您使用的是 PHP 5.4 版本,您可以在您的 publicStaticFunction 中执行以下操作:

$var = function(){
    return self::privateStaticFunction(); 
}; 

$var();

在PHP 5.4中,PHP允许您从lambda函数中访问类作用域。

此外,您是否研究过ReflectionClass?

以下代码可用于以更面向对象的方式替换call_user_func_array():

<?php
$rc = new ReflectionClass('SomeClass');
$class = $rc->newInstanceArgs(array('foo', 'bar'));

echo $class->doSomething();

您可以编写自己的类来使用实现了ReflectionClassReflectionMethod并使用setAccessible()来允许访问受保护和私有方法。


我的评论引发了一些疑问,但是你的回答完全正确。我需要5.4版本。很遗憾我不能选择两个正确答案。 - Felipe

1
这是我解决问题的方法。
class test{
  static function Unix($arr){return implode("/",$arr);}
  static function Windows($arr){return implode("\\",$arr);}
  function test(){
    $slash = "Unix";
    echo self::$slash(["path","to","a","folder"]);
  }
}

我有一种感觉,在旧版本的php上这不会起作用。 - Isaac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接