在PHP中解析类,函数和参数

时间:2009-09-12 11:56:36

标签: php parsing tokenize code-analysis

我想创建一个函数,它接收一个包含PHP文件路径的参数,然后解析给定的文件并返回如下内容:

class NameOfTheClass
   function Method1($arg1, $arg2, $arg2)
   private function Method2($arg1, $arg2, $arg2)
   public function Method2($arg1, $arg2, $arg2)

abstract class AnotherClass
   function Method1($arg1, $arg2, $arg2)
   private function Method2($arg1, $arg2, $arg2)
   public function Method2($arg1, $arg2, $arg2)

function SomeFunction($arg1, $arg2, $arg3)

此函数应返回给定文件中存在的所有类,方法和函数以及所有已定义的标识符(abstract,public,private,protected,static,extends,interfaces,...)。

我的第一个尝试是使用正则表达式来执行此操作,但是这些注释表现得非常糟糕,即:/ *此函数返回(max(salary))* /并且如果我想要正确支持范围,则变得非常复杂。

另一种可能的解决方案是使用以下内置PHP函数:

get_declared_classes
get_declared_interfaces
get_defined_functions
get_class_methods

但是这些函数不允许我查看定义类/方法/函数的文件,因此它不是很有用。

我相信Tokenizer扩展是我的问题的解决方案,但我以前从未使用过这个扩展。

3 个答案:

答案 0 :(得分:9)

如果您使用的是PHP 5,那么Reflection API就是您的工具。

示例:

$class = new ReflectionClass("NameOfTheClass");
$methods = $class->getMethods();
foreach($methods as $m) {
    print $m->name;
    $m->isPrivate() ? print "Private" : print "";
    $m->isPublic() ? print "Public" : print "";
    $params = $m->getParameters();
    foreach($params as $p) {
        print $p->getName();
        }
}

答案 1 :(得分:1)

就像你自己发现的一样,正则表达式不适合这项工作,这里是^^

而且,就像你说的那样,你提出的内置函数也没那么有用 - 只有可能有用的东西是它们允许你知道哪个类存在......但它们也会返回内置类: - (

使用Tokenizer扩展对我来说似乎有点过分/难以理解;我可能不会这样做,实际上:我认为也是“低级别”。


相反,我会看看PHP的Reflection API:它完全存在于反向工程类,接口,函数......

所以,我认为它非常适合你想要做的事情。


编辑:这是一个简单的例子:

首先,让我们尝试对类进行反思:

include dirname(__FILE__) . '/temp-2.php';
$rC = new ReflectionClass('MyFirstClass');

您现在可以找到声明它的文件,以及其中的方法:

var_dump($rC->getFileName());
var_dump($rC->getMethods());

哪能得到你:

string '/home/squale/developpement/tests/temp/temp-2.php' (length=48)

array
  0 => &
    object(ReflectionMethod)[2]
      public 'name' => string '__construct' (length=11)
      public 'class' => string 'MyFirstClass' (length=12)
  1 => &
    object(ReflectionMethod)[3]
      public 'name' => string 'glop' (length=4)
      public 'class' => string 'MyFirstClass' (length=12)


现在,要了解每种方法的信息:

foreach ($rC->getMethods() as $rM) {
    var_dump($rM, $rM->getParameters());
    echo '-----';
}

你会得到:

object(ReflectionMethod)[3]
  public 'name' => string '__construct' (length=11)
  public 'class' => string 'MyFirstClass' (length=12)

array
  0 => &
    object(ReflectionParameter)[4]
      public 'name' => string 'arg1' (length=4)
  1 => &
    object(ReflectionParameter)[5]
      public 'name' => string 'arg2' (length=4)

-----

object(ReflectionMethod)[2]
  public 'name' => string 'glop' (length=4)
  public 'class' => string 'MyFirstClass' (length=12)

array
  0 => &
    object(ReflectionParameter)[5]
      public 'name' => string 'a' (length=1)


从那里,你应该能够挖掘更多;到达你刚才问的那个; - )


作为旁注:有一件事我不知道是:“如何找到在给定文件中声明哪些类/方法”: - (

如果有人有想法,那将是受欢迎的!

答案 2 :(得分:1)

我建议采用以下程序:

  1. 存储get_declared_classesget_declared_interfacesget_defined_functions的当前输出(如果您确实需要支持它们)
  2. 包含文件
  3. get_declared_classesget_declared_interfaces和g et_defined_functions与您存储的内容进行比较以查看新内容
  4. 使用反射来分析它们
  5. 转到下一个文件的第2步