2009-09-12 16 views
5

que quieren crear una función que recibe un solo argumento que contiene la ruta a un archivo PHP y analiza el archivo y devuelve algo como esto:Clases de análisis sintáctico, funciones y argumentos en 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) 

Este La función debe devolver todas las clases, métodos y funciones que existen en el archivo dado con todos los identificadores definidos (abstract, public, private, protected, static, extends, interfaces, ...).

Mi primer pensamiento fue utilizar expresiones regulares para hacer esto, sin embargo, estas se comportan bastante mal con comentarios, es decir:/* esta función devuelve (max (salario)) */y se vuelven bastante complejas si quiero apoyar correctamente los ámbitos .

Otra posible solución era utilizar las siguientes funciones PHP incorporadas:

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 de Tokenizer es la solución a mi problema, sin embargo, nunca antes había usado esta extensión.

Respuesta

8

Si está utilizando PHP 5, el Reflection API 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(); 
     } 
} 
+0

Esto cubre prácticamente todas mis necesidades, una pregunta más difícil: ¿qué pasa con las funciones (no los métodos)? –

+1

Puede usar get_defined_functions() para obtener todas las funciones definidas por usted, anche y no por la clase ReflectionFunction (http://www.php.net/manual/en/class.reflectionfunction.php) para analizarlas. –

1

Al igual que usted descubrió a sí mismo, de expresiones regulares no son del todo la herramienta correcta para el trabajo, aquí ^^

Y, como usted ha dicho, el incorporado en las funciones que propuestas no son de mucha ayuda, ya sea - lo único que podría ser útil es que permiten que sepan que existe la clase ... Pero volverán clases incorporadas también :-(

Usando la extensión Tokenizer parece un poco exagerado/duro para mí, que probablemente no iría de esa manera, en realidad: demasiado "bajo nivel", supongo.


En su lugar, yo wou Eche un vistazo a PHP Reflection API: existe exactamente para realizar ingeniería inversa de clases, interfaces, funciones, ...

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


Editar: Aquí está un ejemplo rápido:

En primer lugar, vamos a tratar de 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 que métodos están en ella:

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

, que pueden ayudarle:

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 '-----'; 
} 

que obtendrá:

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í, usted debe ser capaz de cavar un poco más ; y llegar a lo que se preguntó por primera vez ;-)


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

Si alguien tiene una idea, será bienvenida!

+0

Gracias, parece que el API de reflexión es un fuerte candidato para resolver mi problema. ¿Sabes dónde puedo ver un ejemplo de una implementación similar a mi problema? Además, ¿la API Reflection me permite distinguir en qué archivos se encuentran los métodos/clases encontrados? –

+0

¡Hola! He editado mi respuesta para dar un ejemplo :-) ¡Espero que esto ayude! –

0

no puedo ayudarle con su pregunta en particular, ya que nunca he usado Tokenizer tampoco.

usted no menciona para qué estás usando esto, pero algo como phpDoc harías ed?

+0

Lo que necesito es básicamente una versión simplificada de phpDoc sin la molestia de phpDoc; básicamente, solo quiero echar un vistazo a todos los métodos y argumentos disponibles de cualquier archivo, eso sería más que suficiente para mí. –

1

sugiero el siguiente procedimiento:

  1. tienda de la salida de corriente de get_declared_classes, get_declared_interfaces y get_defined_functions (si es que realmente necesita para apoyarlos)
  2. incluyen el archivo
  3. comparar get_declared_classes, get_declared_interfaces yg et_defined_functions con los ha guardado para ver qué hay de nuevo
  4. utilizar la reflexión para analizarlos
  5. Goto el paso 2 para el siguiente archivo
Cuestiones relacionadas