【问题标题】:Dynamic static method call in PHP?PHP中的动态静态方法调用?
【发布时间】:2011-01-07 16:54:22
【问题描述】:

请有PHP经验的人提供以下帮助。在我的代码中,我调用了一个非实例化类中的公共静态方法:

$result = myClassName::myFunctionName();

但是,我希望有很多这样的类,并根据用户的语言即时确定正确的类名。换句话说,我有:

$language = 'EN';

...我需要做一些类似的事情:

$result = myClassName_EN::myFunctionName();

我知道我可以将语言作为参数传递给函数并在一个公共类中处理它,但由于各种原因,我更喜欢不同的解决方案。

这有意义吗,有人吗?谢谢。

【问题讨论】:

  • 回答你的最后 3 行,不,这没有多大意义,除非你有特定的原因不能实现“传递语言作为参数”的方式
  • 是的,我有一个特定的原因...涉及以更理智的方式管理这些类中发生的各种事情的翻译。这很复杂:)

标签: php class function dynamic


【解决方案1】:

接下来你可以轻松做到:

<?php

class B {

    public static $t = 5;

    public static function t($h) {
        return "Works!" . $h;
    }
}

$g = 't';
$class = 'B';

echo $class::$g('yes'); //Works! Yes

它可以正常工作,在 PHP 5.2 上测试 >=

【讨论】:

    【解决方案2】:

    我知道这是一个旧线程,但从 PHP 5.3.0 开始,您应该使用 forward_static_call

    $result = forward_static_call(array('myClassName_EN', 'myFunctionName'));
    

    使用您的 $language 变量,它可能看起来像:

    $result = forward_static_call(array('myClassName_' . $language, 'myFunctionName'));
    

    【讨论】:

    【解决方案3】:

    解决方案如下:

    $yourClass::myFunctionName();
    

    不会工作。 PHP会产生解析错误。

    不幸的是,唯一的方法是使用非常慢call_user_func()

    【解决方案4】:

    正如 temuri 所说,在尝试 '$className::functionName' 时会产生解析错误:

    解析错误:语法错误,意外的 T_PAAMAYIM_NEKUDOTAYIM ...

    就我而言(带有 2 个参数的静态方法),最好的解决方案是使用带有 2 个数组的 call_user_func_array(如 nikc.org 所建议的那样):

    $result = call_user_func_array(array($className, $methodName), array($ard1, $arg2));
    

    BR

    【讨论】:

      【解决方案5】:

      使用call_user_func函数:

      http://php.net/manual/en/function.call-user-func.php

      例子:

      call_user_func('myClassName_' . $language . '::myFunctionName');
      

      【讨论】:

      • 结合is_callablemethod_exists 这也是我的建议。要传递参数,请查看 call_user_func_array php.net/is_callable php.net/method_exists php.net/call_user_func_array
      • 这种工作方式似乎是最干净的解决方案。谢谢
      • @nikc.org 如果不方便将参数编译成数组,也可以直接将参数传递给call_user_func()
      • 有没有办法使用 ReflectionMethod 类来做到这一点?
      • 需要注意的是也可以这样格式化:call_user_func(['myClassName_' . $language, 'myFunctionName']);
      【解决方案6】:

      我将在工厂中封装您需要的类的创建。

      这样,当您需要更改基本名称或将语言映射到正确类的规则时,您将拥有一个入口点。

          class YourClassFactory {
      
              private $_language;
              private $_basename = 'yourclass';
      
              public YourClassFactory($language) {
                  $this->_language = $language;
              }
      
              public function getYourClass() {
                  return $this->_basename . '_' . $this->_language;
              }    
          } 
      

      然后,当你必须使用它时:

      $yourClass = $yourClassFactoryInstance->getYourClass();
      $yourClass::myFunctionName();
      

      【讨论】:

      【解决方案7】:

      据我所知,您需要获取可以使用get_class 函数完成的类名。另一方面,Reflection class 可以在这里为您提供帮助,这在 OOP 方式的方法、参数等方面非常有用。

      【讨论】:

        【解决方案8】:

        认为你可以这样做:

        $classname = 'myClassName_' . $language;
        $result = $classname::myFunctionName();
        

        这叫Variable Functions

        【讨论】:

        • 对我来说,这是最好的解决方案。根据我的工作台,这也是最快的:直接调用 100.000 次迭代需要 0.28 秒,使用此解决方案需要 0.32,使用 call_user_func 需要 0.47
        • 有时我们需要一个完全限定的类名然后使用这种方式在类中添加命名空间 $className = '\\QuickBooksOnline\\API\Facades\\'.$resource; $postPayload = $className::create();
        【解决方案9】:

        虽然我认为你的交易方式很糟糕,但我想我可能有一个解决方案

        $className = 'myClassName_'.$language;
        $result = $className::myFunctionName();
        

        我想这就是你想要的

        【讨论】:

        • 请你告诉我为什么这是个坏主意?
        • 您可以使用语言作为参数,而不是选择为其定义一个新类。假设你想支持 200 种不同的语言,你会坐下来写 200 种不同的课程吗?它还会使您的代码极难阅读和理解。
        • 啊....不,不会有 200 种语言。以更实际的方式完成其他工作是对良好做法的有意识的降级。
        • 请注意:这仅从 php 5.3 开始有效 - 最好检查您的主机提供商是否支持该版本(我使用的不支持)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-09
        相关资源
        最近更新 更多