Analisando classes, funções e Argumentos em PHP
-
06-07-2019 - |
Pergunta
Eu quero criar uma função que recebe um único argumento que sustenta o caminho para um arquivo PHP e, em seguida, analisa o arquivo e retorna dado algo como isto:
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)
Esta função deve retornar todas as classes, métodos e funções que existem no arquivo fornecido com todos os identificadores definidos (abstrato, público, privado, protegido, estática, estende-se, interfaces, ...).
Meu primeiro ensinei era usar expressões regulares para fazer isso, porém estes se comportam muito mal com os comentários, ou seja: / * Esta função retorna (max (salário)) * / e tornar-se bastante complexa, se eu quiser apoiar adequadamente âmbitos.
Outra solução possível era a utilizar as seguintes funções internas do PHP:
get_declared_classes
get_declared_interfaces
get_defined_functions
get_class_methods
No entanto, estas funções não permitam-me para ver o arquivo onde as classes / métodos / funções são definidas e, portanto, não é muito útil.
Eu acredito que a extensão Tokenizer é a solução para o meu problema, no entanto Eu nunca usei essa extensão antes.
Solução
Se você estiver usando PHP 5, a Reflection API é a sua ferramenta.
Exemplo:
$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();
}
}
Outras dicas
Eu sugiro o seguinte procedimento:
- armazenar a saída de corrente de
get_declared_classes
,get_declared_interfaces
eget_defined_functions
(se você realmente precisa para apoiá-los) - incluir o arquivo
-
get_declared_classes
comparar,get_declared_interfaces
e get_defined_functions
com o que você armazenados para ver o que há de novo - usar o reflexo para analisá-los
- Ir à etapa 2 para o próximo arquivo
Como você descobriu-se, regex são bastante não a ferramenta certa para o trabalho, aqui ^^
E, como você disse, as funções internas que você propostas não são tão úteis ou - única coisa que pode ser útil é que eles permitem que você sabe que existe classe ... Mas eles vão voltar builtin aulas também : - (
Usando a extensão Tokenizer parece um exagero bit / duro para mim; Eu provavelmente não ir por esse caminho, na verdade:. Muito "baixo nível", suponho
Em vez disso, gostaria de dar uma olhada Reflection API do PHP: ela existe exatamente para aulas de engenharia reversa, as interfaces, funções, ...
Então, acho que seria bastante adequado para o que você está tentando fazer.
Edit: aqui está um exemplo rápido:
Primeiro, vamos tentar fazer uma reflexão sobre uma classe:
include dirname(__FILE__) . '/temp-2.php';
$rC = new ReflectionClass('MyFirstClass');
Agora você pode descobrir em qual arquivo foi declarado, e quais os métodos estão nele:
var_dump($rC->getFileName());
var_dump($rC->getMethods());
O que você irá obter:
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)
E agora, para obter informações sobre cada método:
foreach ($rC->getMethods() as $rM) {
var_dump($rM, $rM->getParameters());
echo '-----';
}
Você vai ter:
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)
De lá, você deve ser capaz de cavar um pouco mais; e chegar ao que você pediu em primeiro lugar; -)
Como nota: há uma coisa que eu não tenho nenhuma idéia sobre é: " como encontrar quais classes / métodos são declaradas em um dado arquivo ": - (
Se alguém tiver uma idéia, ele será bem-vindo!