如何找到PHP文件中使用的所有类?

时间:2013-02-13 01:05:22

标签: php class code-analysis tokenize

我正在尝试使用tokenizer扫描文件以查找所有已定义的类,它们扩展的任何内容,任何创建的实例以及静态调用它们的任何时间。

<?php

$tokens = token_get_all(file_get_contents($file));

$used_classes = array();
$defined_classes = array();
$variable_classes = array();

foreach($tokens as $i => $token) {

    if(is_array($token)) {

        if(isset($tokens[$i - 2][0], $tokens[$i - 1][0])) {

            // new [class]
            if ($tokens[$i - 2][0] == T_NEW AND $tokens[$i - 1][0] == T_WHITESPACE) {

                if($tokens[$i][0] == T_STRING) {
                    $used_classes[$token[1]] = TRUE;

                // new $variable()
                } elseif($tokens[$i][0] == T_VARIABLE) {    

                    // @todo, this is really broken. However, do best to look for the assignment
                    if(preg_match('~\$var\s*=\s*([\'"])((?:(?!\1).)*)\1~', $text, $match)) {
                        if(empty($extension_classes[$match[2]])) {
                            $used_classes[$match[2]] = TRUE;
                        }
                    } elseif($token[1] !== '$this') {
                        $variable_classes[$token[1]] = TRUE;
                    }
                }

            }

            // class [class]
            if ($tokens[$i - 2][0] == T_CLASS AND $tokens[$i - 1][0] == T_WHITESPACE) {

                if($tokens[$i][0] == T_STRING) {
                    $defined_classes[$token[1]] = TRUE;
                }
            }


            // @todo: find more classes \/

            // class [classname] extends [class] ???
            // [class]::method()???
        }
    }
}

如何扩展此代码以查找上述任何其他PHP类实例?

4 个答案:

答案 0 :(得分:2)

解析然后解释PHP代码并不能使用正则表达式很好地解决。你需要一个更聪明的东西,比如状态机,它实际上可以理解诸如范围,类名,继承等之类的东西,以便能够做你想要的。

就是这样,我碰巧编写了一个基于状态机的PHP-to-Javascript转换器,它几乎完成了你想做的大部分工作:

  

所有已定义的类

是的,所有类都创建了一个ClassScope,其中列出了所有变量,并且它们的方法是作为FunctionScope创建的,因此您可以确定类具有哪些方法。

  

他们延伸的任何东西

是的,每个班级都有ClassScope中列出的父类 - &gt; $ parentClasses

  

任何创建的实例

不,但要添加额外的代码来记录这些代码并不困难。

  

随时静态调用它们。

不 - 但实际上可以使用正则表达式完成。

虽然它并没有完全解决你的问题,但是现有的项目可以让你达到你想要做的95%,这将节省几个星期的工作。

答案 1 :(得分:0)

Inclued可能值得在这里查看,但我认为它不会为您提供任何数据,不包括文件/类以及多少次。

答案 2 :(得分:0)

我不认为你可以通过分析令牌来做到这一点。

对于任何类名,您需要知道它所代表的实际定义,包括任何继承关系,以及它是否已在您的代码中用于实现接口。类/接口定义可以在另一个文件中;该文件可能包含在某些条件下。您可能在不同的文件中以不同的方式定义相同的类名。因此,通常您需要一次处理组成系统的所有文件。

作为基础所需要的是一个解析PHP并构建真实符号表的工具。您可以从中计算结果。 (这样的工具将令牌分析为起点,但它比琐碎的令牌扫描要多得多。)

答案 3 :(得分:0)

如果您只是加载代码,则可以使用内置的Reflection API(ReflectionClass::_construct()等)来检查每个类。

要自己获取课程,请使用内置的get_declared_classes()

(注意:我没试过这个,所以YMMV。)