Classi di analisi, funzioni e argomenti in PHP
-
06-07-2019 - |
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.
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:
- archivia l'output corrente di
get_declared_classes
,get_declared_interfaces
eget_defined_functions
(se hai davvero bisogno di supportarli) - includi il file
- confronta
get_declared_classes
,get_declared_interfaces
e get_defined_functions
con quelli che hai archiviato per vedere le novità - usa la riflessione per analizzarli
- 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!