【问题标题】:I need to collect an array of classes to call their static variables in php我需要收集一个类数组来在 php 中调用它们的静态变量
【发布时间】:2009-07-08 09:44:25
【问题描述】:

首先我想说这不是一个容易解释的问题,所以如果它看起来令人困惑,请耐心等待。

我有一组这样的类

class Product {

   public static $static_type = 'product';
   public static $static_table = 'product_table';

   public function __construct($params) { //do some }
}

然后是新闻、事件等类

我需要从另一个类以迭代的方式访问这些类中的那些静态变量。比如:

//...
if (Product::$static_type) { //do some }
else if (News::$static_type) { //do other }
//...

我想在一个循环中对其进行改造,比如 foreach 以这样的方式(这不正确,但对我的问题有意义)

foreach ($classes as $class) {
  echo $class::$static_type; //brrrr, just to render the idea :)
}

所以我想到了一个单例/静态类,它有一个静态方法返回我的类数组(未实例化)。像这样:

class Conf {

    public function __construct() {
          //nothing
        }

    public static function get_class_array () {

       //how to do this???
    }
}

然后

foreach (Conf::get_class_array() as $class) {
  echo $class::$static_type; //brrrr, just to render the idea :)
}

我怎样才能做到这一点?在这种情况下,我不想实例化 Product、News 或其他。

编辑:eval 是邪恶的,我不想使用它。 get_declared_class 没有技巧,如果没有办法解决我会使用反射,我认为这是提到的更优雅的方式:(。

编辑:同时我会以这种方式执行 Conf::get_class_array()

public static function get_class_array () {
   return array(new ReflectionClass('Prodotto'), new ReflectionClass('News'));
}

然后在这里调用它:

foreach (Conf::get_class_array() as $class) {
  echo $class->getStaticPropertyValue('static_type');
}

【问题讨论】:

    标签: php oop static class


    【解决方案1】:

    我认为你做不到。但是,您可以执行以下操作之一:

    $properties = get_class_vars('Product');
    echo $properties['static_type'];
    

    $class = new ReflectionClass('product');
    echo $class->getStaticPropertyValue('static_type');
    

    请注意,在 PHP 5.3 中 echo $class::$static_type; 可以工作 (http://php.net/manual/en/language.oop5.static.php)

    【讨论】:

      【解决方案2】:

      直到5.3.0,你都可以试试这个方法。按照您的建议创建一个容器类(我们将其称为 Conf 以坚持您所拥有的),并提供两种方法来设置和获取您想要迭代的适用类:

      <?php
      
      class Conf {
          private static $instance;
          private $classes = array();
      
          public static function getInstance() {
              if ( is_null(self::$instance) ) {
                  self::$instance = new self();
              }
      
              return self::$instance;
          }
      
          public function registerClass($className) {
              // Use associative index to maintain uniqueness
              $this->classes[$className] = $className;
          }
      
          public function getRegisteredClasses() {
              return $this->classes;
          }
      }
      

      一些示例类以及如何注册它们:

      class X {
          public static $a = "catus";
          public static $b = "pants";
      }
      
      class Y {
          public static $a = "apples";
          public static $b = "bananers";
      }
      
      $conf = Conf::getInstance();
      $conf->registerClass("X");
      $conf->registerClass("Y");
      

      现在,要访问和/或更改静态成员,您可以执行以下操作(使用 RefelectionClass,正如 Tom Haigh 指出的那样):

      $conf = Conf::getInstance();
      
      echo "<pre>";
      foreach ( $conf->getRegisteredClasses() as $class ) {
          $reflection = new ReflectionClass($class);
      
          echo "<hr/>Class: $class\n";
      
          // Access example
          print_r( $reflection->getStaticProperties() );
      
          // Alter example
          $reflection->setStaticPropertyValue("a", 
               $reflection->getStaticPropertyValue("a") . "-modified"
          );
          print_r( $reflection->getStaticProperties() );
      
      }
      

      如果您有像 Com_Example_Static_XCom_Example_Static_Y 这样的类命名约定,则可以按照 n3rd 的建议简化 Conf-&gt;getRegisteredClasses()(如果您愿意,甚至可以将其设为静态方法):

      class Conf {
          // ....
      
          static public function getMatchingClasses($pattern="/^Com_Example_Static_.+$/") {
              $response = array();
              foreach ( get_declared_classes() as $className ) {
                  if ( preg_match($pattern, $className, $m) ) {
                      $response[] = $className;
                  }
              }
      
              return $response;
          }
      }
      

      当然,将您的foreach 更新为:

      foreach ( Conf::getMatchingClasses() as $class ) {
          // ...
      }
      

      希望对您有所帮助。

      【讨论】:

      • 有趣的一点,但我想我会做的更简单,总是使用反射。 “注册”课程是个好主意。
      【解决方案3】:

      您可以使用get_declared_classes() 获取课程列表。不过,这将是所有类,而不仅仅是您声明的类。

      你应该让你的所有类都继承自一个基类:

      类产品扩展 MyBase {}

      然后你可以这样列出类

      function get_class_array()
      {
          $myClasses = array();
          foreach (get_declared_classes as $class)
          {
              if (is_subclass_of($class, 'MyBase'))
                  $myClasses[] = $class;
          }
      
          return $myClasses;
      }
      

      那么就可以这样获取数据了:

      foreach (get_class_array() as $class)
          echo eval("return $class::\$foo;"); // Yes yes, eval is evil, we know...
      

      【讨论】:

      • 它们已经从基类继承,但 eval 是邪恶的(是的,我们知道 =)),我对一种可能更清洁的方式感兴趣
      【解决方案4】:

      要获取课程列表,您可以使用get_declared_classes。然后,您必须确定要处理哪些类。

      您可以通过使用is_subclass_of 查找公共基类,或使用ReflectionClass 来查看它是否具有您感兴趣的静态成员变量。

      【讨论】:

        【解决方案5】:

        我认为没有简单的方法可以做到这一点。以下是我脑海中浮现的一些想法:

        • 使用get_declared_classes() 检索所有已定义类的列表,并根据您的命名方案(例如MyNamespace_*)或它们是否实现接口(例如MyStaticEnumerable)检查它们。
        • 有点像上面的,但更复杂一点:在class loader 上写下你的,让它检查加载的类是否是你想要枚举的类之一。如果是这样,请让某些经理类知道。
        • 检查定义类的目录以手动枚举所有类。

        【讨论】:

          猜你喜欢
          • 2021-05-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多