在PHP中将静态方法作为参数传递


Passing static methods as arguments in PHP

在PHP中,是否可以执行以下操作:

myFunction( MyClass::staticMethod );

这样"myFunction"将引用静态方法并能够调用它。当我尝试它时,我会得到一个错误"Undefined class constant"(PHP 5.3),所以我想这不是直接可能的,但有没有类似的方法?到目前为止,我最接近的方法是将"function"作为字符串传递,并使用call_user_func()。

实现这一点的"php方法"是使用与is_callable和call_user_func完全相同的语法。

这意味着你的方法对是"中立的"

  • 标准函数名称
  • 静态类方法
  • 实例方法
  • 一个闭包

在静态方法的情况下,这意味着您应该将其传递为:

myFunction( [ 'MyClass', 'staticMethod'] );

或者如果你还没有运行PHP 5.4:

myFunction( array( 'MyClass', 'staticMethod') );

由于您已经提到使用了call_user_func(),并且您对使用该解决方案或将静态函数作为字符串传递的解决方案不感兴趣,因此这里有一个替代方案:使用匿名函数作为静态函数的包装器。

function myFunction( $method ) {
    $method();
}
myFunction( function() { return MyClass::staticMethod(); } );

我不建议这样做,因为我认为call_user_func()方法更简洁。

如果您想避免字符串,可以使用以下语法:

myFunction( function(){ return MyClass::staticMethod(); } );

它有点冗长,但它的优点是可以进行静态分析。换句话说,IDE可以很容易地指出静态函数名称中的错误。

让我试着举一个彻底的例子

你会打这样的电话:

myFunction('Namespace''MyClass', 'staticMethod');

或者像这样(如果你有想要传递的参数):

myFunction('Namespace''MyClass', 'staticMethod', array($arg1, $arg2, $arg3));

以及您接收此呼叫的功能:

public static function myFunction($class, $method, $args = array())
{
    if (is_callable($class, $method)) {
        return call_user_func_array(array($class, $method), $args);
    }
    else {
        throw new Exception('Undefined method - ' . $class . '::' . $method);
    }
}

类似技术通常用于php中的Decorator模式。

问题:

在PHP中,可以做这样的事情吗:

myFunction(MyClass::staticMethod);

答案是肯定的。您可以让staticMethod()返回匿名函数。即

private static function staticMethod()
{
    return function($anyParameters)
    {
        //do something here what staticMethod() was supposed to do
        // ...
        // ...
        //return something what staticMethod() was supposed to return;
    };
}

然后你可以写

myFunction(MyClass::staticMethod());

但请注意,调用staticMethod()需要()。这是因为它现在返回了一个匿名函数,该函数封装了您最初希望静态方法()执行的任务

当staticMethod()仅作为参数传入另一个函数时,这种方法非常有效。如果您希望调用staticMethod()来直接进行处理,则必须编写

MyClass::staticMethod()($doPassInParameters);

请注意,这可能需要一个额外的冗余步骤来检索函数指针,而不需要将其包装在匿名函数中即可工作。我只使用它作为参数传递,所以不确定额外步骤的性能损失。也许可以忽略不计。。。

这是因为传递常量和函数之间的区别。传递不带括号的参数名称表示常量(MyClass::staticMethod),带括号表示静态函数(MyClass::staticMethod())。

这将显示第一次呼叫为6第二次呼叫为9在输出中。

$staticmethod1 = function ($max)
{
    return $max*2;
};
$staticmethod2 = function ($max)
{
    return $max*$max;
};
function myfunction($x){
    echo $x(3);
}
myfunction($staticmethod1);
myfunction($staticmethod2);

从PHP 7.4开始,这既方便又友好:

myFunction(fn() => MyClass::staticMethod());