使用get_declared_classes()只输出我声明的类,而不是PHP自动执行的类

时间:2012-02-02 07:42:32

标签: php

有点好奇,但是我想用我用这样的东西声明的类中创建一个数组

foreach(get_declared_classes() as $class)
    $c[] = $class;


print_r($c);

唯一的问题是我得到的东西就像我加载的类一样:

stdClass
Exception
ErrorException
Closure
DateTime
DateTimeZone
DateInterval
DatePeriod
LibXMLError
LogicException
BadFunctionCallException
BadMethodCallException
DomainException
InvalidArgumentException
LengthException
OutOfRangeException
RuntimeException
OutOfBoundsException
OverflowException
RangeException
UnderflowException
UnexpectedValueException
RecursiveIteratorIterator
IteratorIterator
{...}
SQLiteResult
SQLiteUnbuffered
SQLiteException
SQLite3
SQLite3Stmt
SQLite3Result
XMLReader
XMLWriter
XSLTProcessor
ZipArchive

是否有一个只加载用户特定类而不是系统加载类的函数?或者是一个限制foreach列出这些类的条件语句?

6 个答案:

答案 0 :(得分:13)

Reflection API可以检测类是否为内部类。 ReflectionClass::isInternal检查类是否是内部的,而不是用户定义的:

$userDefinedClasses = array_filter(
    get_declared_classes(),
    function($className) {
        return !call_user_func(
            array(new ReflectionClass($className), 'isInternal')
        );
    }
);

上面的代码将检查并删除内部get_declared_classes返回的每个类,只留下用户定义的类。这样,您就不需要像本页其他地方所建议的那样创建和维护内部类的数组。

答案 1 :(得分:12)

没有内置函数可以实现这一点,但您可以在声明任何内容之前get_declared_classes将其存储在全局变量中,例如$predefinedClasses。然后,您需要使用的地方:

print_r(array_diff(get_declared_classes(), $predefinedClasses));

答案 2 :(得分:5)

没有直接内置的可能性,但您可以执行以下操作:

  1. 在您的脚本开头,致电get_declared_classes()并将其存储到$php_classes
  2. 等变量 加载课程后
  3. ,再次致电get_declared_classes()并使用array_diff()过滤掉$php_classes - 结果是您自己的课程列表。

    // start
    $php_classes = get_declared_classes();
    
    // ...
    // some code loading/declaring own classes
    // ...
    
    // later
    $my_classes = array_diff(get_declared_classes(), $php_classes);
    

答案 3 :(得分:1)

以下是我的解决方案,它实际上可以正常工作并且不会影响性能。 这只为您提供了项目中定义的类,没有别的。 确保在加载所有类之后尽可能晚地运行它。

/**
 * Get all classes from a project.
 *
 * Return an array containing all classes defined in a project.
 *
 * @param string $project_path
 * @return array
 */
function smk_get_classes_from_project( $project_path ){
    // Placeholder for final output
    $classes = array();

    // Get all classes
    $dc = get_declared_classes();

    // Loop
    foreach ($dc as $class) {
        $reflect = new \ReflectionClass($class);

        // Get the path to the file where is defined this class.
        $filename = $reflect->getFileName();

        // Only user defined classes, exclude internal or classes added by PHP extensions.
        if( ! $reflect->isInternal() ){

            // Replace backslash with forward slash.
            $filename = str_replace(array('\\'), array('/'), $filename);
            $project_path = str_replace(array('\\'), array('/'), $project_path);

            // Remove the last slash. 
            // If last slash is present, some classes from root will not be included.
            // Probably there's an explication for this. I don't know...
            $project_path = rtrim( $project_path, '/' );

            // Add the class only if it is defined in `$project_path` dir.
            if( stripos( $filename, $project_path ) !== false ){
                $classes[] = $class;
            }

        }
    }

    return $classes;    
}

测试。

此示例假定项目具有以下路径:/srv/users/apps/my-project-name

echo '<pre>';
print_r( smk_get_classes_from_project( '/srv/users/apps/my-project-name' ) );
echo '</pre>';

答案 4 :(得分:0)

另一种可能的做法是:

$a= get_declared_classes();

// All user-defined classes

print_r(array_slice(get_declared_classes(), count($a)));

答案 5 :(得分:0)

@Gordon的答案非常好, @Dmitry的解决方案也很好,但是只有当您的课程位于不同的文件中并且包含了它们时,它才有效:

await this.connection.transaction(async transactionalEntityManager => {
                try {
                    urDTOCreated = await this.myService1.createSomething(urDTO, transactionalEntityManager);
                    typeDTOCreated = await this.myService2.createSomethingElse(obj1, obj2, transactionalEntityManager);
                }
                catch (ex) {
                    Logger.log(ex);
                    throw new InternalServerErrorException("Error saving data to database");
                }

但是,如果文件中除了包含的类之外还有其他类,并且如果您不想使用$predefinedClasses = get_declared_classes(); include('Myclass.php'); // This will show class A {} // This will not show print_r(array_diff(get_declared_classes(), $predefinedClasses)); ,那么我会想到一个(疯狂的)想法:

Reflection