Парсинг классов, функций и аргументов в PHP - PullRequest
6 голосов
/ 12 сентября 2009

Я хочу создать функцию, которая получает единственный аргумент, содержащий путь к файлу 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)

Эта функция должна возвращать все классы, методы и функции, которые существуют в данном файле со всеми определенными идентификаторами (абстрактные, публичные, закрытые, защищенные, статические, расширяемые, интерфейсы, ...).

Моей первой попыткой было использование регулярных выражений для этого, однако они плохо работают с комментариями, например: / * эта функция возвращает (max (salary)) * / и становится довольно сложной, если я хочу должным образом поддерживать области видимости.

Другим возможным решением было использование следующих встроенных функций PHP:

get_declared_classes
get_declared_interfaces
get_defined_functions
get_class_methods

Однако эти функции не позволяют мне увидеть файл, в котором определены классы / методы / функции, и поэтому он не очень полезен.

Я считаю, что расширение Tokenizer - решение моей проблемы, однако я никогда не использовал это расширение раньше.

Ответы [ 3 ]

9 голосов
/ 12 сентября 2009

Если вы используете 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 голос
/ 12 сентября 2009

Я предлагаю следующую процедуру:

  1. хранит текущий вывод get_declared_classes, get_declared_interfaces и get_defined_functions (если вам действительно нужно их поддерживать)
  2. включает файл
  3. сравните get_declared_classes, get_declared_interfaces и g et_defined_functions с теми, которые вы сохранили, чтобы увидеть, что нового
  4. использовать отражение, чтобы проанализировать их
  5. перейти к шагу 2 для следующего файла
1 голос
/ 12 сентября 2009

Как вы сами узнали, регулярные выражения - совсем не подходящий инструмент для работы, здесь ^^

И, как вы сказали, предложенные вами встроенные функции тоже не очень полезны - единственное, что может быть полезно, это то, что они позволяют вам знать, какой класс существует ... Но они также будут возвращать встроенные классы. : - (

Использование расширения 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)


Оттуда вы сможете больше копать; и получите то, что вы сначала спросили; -)


Как примечание: есть одна вещь, о которой я понятия не имею: « как найти, какие классы / методы объявлены в данном файле »: - (

Если у кого-то есть идея, она будет приветствоваться!

...