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.

Foi útil?

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:

  1. armazenar a saída de corrente de get_declared_classes, get_declared_interfaces e get_defined_functions (se você realmente precisa para apoiá-los)
  2. incluir o arquivo
  3. get_declared_classes comparar, get_declared_interfaces e get_defined_functions com o que você armazenados para ver o que há de novo
  4. usar o reflexo para analisá-los
  5. 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!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top