Domanda

Voglio creare una funzione che riceve un singolo argomento che contiene il percorso di un file PHP e quindi analizza il file dato e restituisce qualcosa del genere:

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)

Questa funzione dovrebbe restituire tutte le classi, i metodi e le funzioni esistenti nel file dato con tutti gli identificatori definiti (astratto, pubblico, privato, protetto, statico, esteso, interfacce, ...).

Il mio primo pensiero è stato quello di utilizzare espressioni regolari per fare ciò, tuttavia queste si comportano piuttosto male con i commenti, cioè: / * questa funzione restituisce (max (stipendio)) * / e diventa piuttosto complessa se voglio supportare correttamente gli ambiti.

Un'altra possibile soluzione era utilizzare le seguenti funzioni PHP integrate:

get_declared_classes
get_declared_interfaces
get_defined_functions
get_class_methods

Tuttavia queste funzioni non mi permettono di vedere il file in cui sono definite le classi / metodi / funzioni e quindi non è molto utile.

Credo che l'estensione Tokenizer sia la soluzione al mio problema, tuttavia non ho mai usato questa estensione prima.

È stato utile?

Soluzione

Se si utilizza PHP 5, API di riflessione è il tuo strumento.

Esempio:

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

Altri suggerimenti

Suggerisco la seguente procedura:

  1. archivia l'output corrente di get_declared_classes , get_declared_interfaces e get_defined_functions (se hai davvero bisogno di supportarli)
  2. includi il file
  3. confronta get_declared_classes , get_declared_interfaces e g et_defined_functions con quelli che hai archiviato per vedere le novità
  4. usa la riflessione per analizzarli
  5. vai al passaggio 2 per il file successivo

Come hai scoperto tu stesso, regex non è proprio lo strumento giusto per il lavoro, qui ^^

E, come hai detto, le funzioni integrate che hai proposto non sono altrettanto utili - l'unica cosa che potrebbe essere utile è che ti permettono di sapere quale classe esiste ... Ma restituiranno anche le classi integrate : - (

L'uso dell'estensione Tokenizer mi sembra un po 'eccessivo / difficile per me; Probabilmente non vorrei andare così, in realtà: troppo "basso livello", suppongo.


Darei invece un'occhiata alla API di riflessione di PHP: esiste esattamente per classi, interfacce, funzioni di reverse engineering, ...

Quindi, suppongo che sarebbe abbastanza adatto per quello che stai cercando di fare.


Modifica: ecco un breve esempio:

Per prima cosa, proviamo a riflettere su una classe:

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

Ora puoi scoprire in quale file è stato dichiarato e quali metodi sono presenti:

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

Che ti porterà:

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 ora, per ottenere informazioni su ciascun metodo:

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

Otterrai:

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)


Da lì, dovresti essere in grado di scavare un po 'di più; e arriva a quello che hai chiesto per la prima volta ;-)


Come sidenote: c'è una cosa di cui non ho idea è: " come trovare quali classi / metodi sono dichiarati in un dato file " : - (

Se qualcuno ha un'idea, sarà il benvenuto!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top