Pregunta

Quiero crear una función que reciba un único argumento que contenga la ruta a un archivo PHP y luego analice el archivo dado y devuelva algo como esto:

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 función debe devolver todas las clases, métodos y funciones que existen en el archivo dado con todos los identificadores definidos (abstracto, público, privado, protegido, estático, extendido, interfaces, ...).

Mi primer pensamiento fue usar expresiones regulares para hacer esto, sin embargo, estos se comportan bastante mal con los comentarios, es decir: / * esta función devuelve (max (salario)) * / y se vuelve bastante compleja si quiero soportar adecuadamente los ámbitos.

Otra posible solución fue utilizar las siguientes funciones PHP integradas:

get_declared_classes
get_declared_interfaces
get_defined_functions
get_class_methods

Sin embargo, estas funciones no me permiten ver el archivo donde se definen las clases / métodos / funciones y, por lo tanto, no es muy útil.

Creo que la extensión Tokenizer es la solución para mi problema, sin embargo, nunca he usado esta extensión antes.

¿Fue útil?

Solución

Si está utilizando PHP 5, la API de reflexión es su herramienta.

Ejemplo:

$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();
        }
}

Otros consejos

Sugiero el siguiente procedimiento:

  1. almacenar la salida actual de get_declared_classes , get_declared_interfaces y get_defined_functions (si realmente necesita admitirlos)
  2. incluye el archivo
  3. compare get_declared_classes , get_declared_interfaces y g et_defined_functions con los que almacenó para ver las novedades
  4. usa la reflexión para analizarlos
  5. vaya al paso 2 para el siguiente archivo

Como descubrió usted mismo, las expresiones regulares no son la herramienta adecuada para el trabajo, aquí ^^

Y, como dijiste, las funciones integradas que propusiste tampoco son tan útiles, lo único que podría ser útil es que te permiten saber qué clase existe ... Pero también devolverán clases integradas :-(

Usar la extensión Tokenizer me parece un poco exagerado / difícil; Probablemente no iría por ese camino, en realidad: también "bajo nivel", supongo.


En cambio, echaría un vistazo a la API de reflexión de PHP: existe exactamente para clases de ingeniería inversa, interfaces, funciones, ...

Entonces, supongo que sería bastante adecuado para lo que está tratando de hacer.


Editar: aquí hay un ejemplo rápido:

Primero, intentemos hacer una reflexión sobre una clase:

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

Ahora puede averiguar en qué archivo se declaró y qué métodos contiene:

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

Que te llevará:

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)


Y ahora, para obtener información sobre cada método:

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

Obtendrás:

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)


A partir de ahí, deberías poder cavar un poco más; y llega a lo que primero preguntaste ;-)


Como nota al margen: hay una cosa de la que no tengo idea es: " cómo encontrar qué clases / métodos se declaran en un archivo dado " :-(

Si alguien tiene una idea, ¡será bienvenido!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top