Анализ классов, функций и аргументов в PHP
-
06-07-2019 - |
Вопрос
Я хочу создать функцию, которая получает один аргумент, содержащий путь к файлу 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 — это решение моей проблемы, однако я никогда раньше не использовал это расширение.
Решение
Если вы используете PHP 5, 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();
}
}
Другие советы
Я предлагаю следующую процедуру:
<Ол> get_declared_classes
, get_declared_interfaces
и get_defined_functions
(если вам действительно нужно их поддерживать) get_declared_classes
, get_declared_interfaces
и g et_defined_functions
с теми, которые вы сохранили, чтобы увидеть, что нового Как вы сами выяснили, регулярные выражения — совершенно неподходящий инструмент для этой работы, здесь ^^
И, как вы сказали, предложенные вами встроенные функции тоже не так уж и полезны - единственное, что может быть полезно, это то, что они позволяют вам узнать, какой класс существует...Но они также вернут встроенные классы :-(
Использование расширения Tokenizer кажется мне немного излишним/сложным;На самом деле, я бы, наверное, не пошел по этому пути:слишком "низкоуровневый", я полагаю.
Вместо этого я бы взглянул на PHP 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)
Оттуда вы сможете покопать еще немного;и придем к тому, что вы сначала спросили ;-)
В качестве примечания:есть одна вещь, о которой я понятия не имею:"как узнать, какие классы/методы объявлены в данном файле" :-(
Если у кого-то есть идеи, буду рад!