简体   繁体   English

我需要收集一个类数组来在php中调用它们的静态变量

[英]I need to collect an array of classes to call their static variables in php

First thing i want to say that it's not an easy question to explain, so please be patient if it seems confusing. 首先我要说的是,这不是一个容易解释的问题,所以如果它看起来令人困惑,请耐心等待。

I have a set of classes like this 我有一组像这样的课程

class Product {

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

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

and then there are the classes News, Events etc 然后是新闻,活动等课程

From another class i need to access to those static variables inside these classes in an iterative way. 从另一个类我需要以迭代的方式访问这些类中的那些静态变量。 Something like: 就像是:

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

I want to trasform it in a cycle, like foreach in a way like this (it's not correct but makes sense to my question) 我希望在一个循环中对它进行转换,就像foreach一样(这是不正确的,但对我的问题有意义)

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

So i think about a singleton/static class that has a static method returning an array of my classes (not instantiated). 所以我想一个单例/静态类,它有一个静态方法返回我的类数组(没有实例化)。 Like this: 像这样:

class Conf {

    public function __construct() {
          //nothing
        }

    public static function get_class_array () {

       //how to do this???
    }
}

and then 然后

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

How i can reach this? 我怎么能达到这个目标? I don't want to instantiate Product, News or others in this case. 在这种情况下,我不想实例化产品,新闻或其他内容。

Edit: eval is evil, i don't want to use it. 编辑:eval是邪恶的,我不想使用它。 No tricks with get_declared_class , if there's no way to solve I will use reflection, that i think it's the more elegant way among the mentioned :(. 没有get_declared_class技巧,如果没有办法解决我将使用反射,我认为这是提到的更优雅的方式:(。

Edit: in the meantime i'll do the Conf::get_class_array() in this way 编辑:在此期间我将以这种方式执行Conf :: get_class_array()

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

and then call it here: 然后在这里调用它:

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

I don't think you can do this. 我认为你不能做到这一点。 You could however do one of these: 但是你可以做其中一个:

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

or 要么

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

Note that in PHP 5.3 echo $class::$static_type; 注意在PHP 5.3中echo $class::$static_type; will work ( http://php.net/manual/en/language.oop5.static.php ) 将工作( http://php.net/manual/en/language.oop5.static.php

Until 5.3.0, you can try this method. 在5.3.0之前,您可以尝试这种方法。 Create a container class as you suggested (we'll call it Conf to stick with what you had), and provide two methods for setting and getting applicable classes that you want to iterate over: 按照你的建议创建一个容器类(我们称之为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;
    }
}

Some example classes and how to register them: 一些示例类以及如何注册它们:

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

Now, to access and/or alter the static members, you can do something like the following (using RefelectionClass as tom Haigh pointed out): 现在,要访问和/或更改静态成员,您可以执行以下操作(使用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() );

}

If you have a class naming convention like Com_Example_Static_X and Com_Example_Static_Y , you can simplify Conf->getRegisteredClasses() (and even make it a static method if you so desire) by doing as n3rd suggested: 如果您有类命名约定,如Com_Example_Static_XCom_Example_Static_Y ,您可以通过执行n3rd建议简化Conf->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;
    }
}

And, of course, update your foreach to: 当然,请将您的foreach更新为:

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

Hope that was helpful. 希望这很有帮助。

You can use get_declared_classes() to get a list of classes. 您可以使用get_declared_classes()来获取类列表。 This will be all class though, not just the ones you've declared. 这将是所有课程,而不仅仅是你宣布的课程。

You should make all your classes inherit from a base class: 您应该使所有类继承自基类:

class Product extends MyBase {} class Product扩展MyBase {}

Then you can list the classes like this 然后你可以列出这样的类

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

    return $myClasses;
}

Then you can get the data like this: 然后你可以得到这样的数据:

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

To get a list of classes, you can use get_declared_classes . 要获取类列表,可以使用get_declared_classes Then you'll have to determine which of those classes you want to process. 然后,您必须确定要处理哪些类。

You could do this by looking for a common base class with is_subclass_of , or using ReflectionClass to see if it has the static member variables you are interested in. 您可以通过使用is_subclass_of查找公共基类,或使用ReflectionClass查看它是否具有您感兴趣的静态成员变量来完成此操作。

I don't think there's an easy way to do this. 我认为没有一种简单的方法可以做到这一点。 Here are a few ideas off the top of my head how you could go about doing this: 以下是一些关于如何做到这一点的想法:

  • Use get_declared_classes() to retrieve a list of all defined classes and check them against your naming scheme (eg MyNamespace_* ) or whether they implement an interface (eg MyStaticEnumerable ). 使用get_declared_classes()检索所有已定义类的列表,并根据您的命名方案(例如MyNamespace_* )或它们是否实现接口(例如MyStaticEnumerable )进行检查。
  • Kinda like the above, but a little more sophisticated: write your on class loader and have it check whether a loaded class is one of ones you want to enumerate. 有点像上面的,但更复杂一点:编写你的类加载器 ,并检查加载的类是否是你想要枚举的类之一。 If so, make it known to some manager class. 如果是这样,请让某些经理班知道。
  • Check the directory in which the classes are defined to manually enumerate all classes. 检查定义类的目录以手动枚举所有类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM