2014-08-30 16 views
7

È possibile riflettere o visualizzare la fonte di un oggetto di chiusura PHP? Cioè, se faccio qualcosa di simileVisualizzazione di una sorgente di chiusura di PHP

$closure = function() 
{ 
    return 'Hi There'; 
}; 

e poi qualcosa di simile

var_dump($closure); 

uscite PHP

object(Closure)[14] 

Cioè, so che l'oggetto è una chiusura, ma ho non ho idea di cosa faccia.

Sto cercando un metodo di riflessione, una funzione o un'estensione di debug che mi consenta di scaricare il corpo reale della funzione anonima.

risposta

10

Ciò che è possibile ottenere da PHP è limitato, utilizzando la reflection è possibile ottenere solo la firma dei parametri della funzione e la riga di inizio e di fine del file del codice sorgente. Ho una volta scritto un articolo del blog su questo: http://www.metashock.de/2013/05/dump-source-code-of-closure-in-php/ ...

E mi portano al seguente codice, utilizzando la riflessione:

function closure_dump(Closure $c) { 
    $str = 'function ('; 
    $r = new ReflectionFunction($c); 
    $params = array(); 
    foreach($r->getParameters() as $p) { 
     $s = ''; 
     if($p->isArray()) { 
      $s .= 'array '; 
     } else if($p->getClass()) { 
      $s .= $p->getClass()->name . ' '; 
     } 
     if($p->isPassedByReference()){ 
      $s .= '&'; 
     } 
     $s .= '$' . $p->name; 
     if($p->isOptional()) { 
      $s .= ' = ' . var_export($p->getDefaultValue(), TRUE); 
     } 
     $params []= $s; 
    } 
    $str .= implode(', ', $params); 
    $str .= '){' . PHP_EOL; 
    $lines = file($r->getFileName()); 
    for($l = $r->getStartLine(); $l < $r->getEndLine(); $l++) { 
     $str .= $lines[$l]; 
    } 
    return $str; 
} 

Se si dispone la seguente chiusura:

$f = function (Closure $a, &$b = -1, array $c = array()) 
    use ($foo) 
{ 
    echo $this->name; 
    echo 'test'; 
}; 

closure_dump() darà i seguenti risultati:

function (Closure $a, &$b = -1, array $c = array (
)){ 
use ($foo) 
{ 
    echo $this->name; 
    echo 'test'; 
}; 

potete vedere, è imperfetto (il parametro dell'array). Inoltre, non gestirà correttamente alcuni casi di bordi, specialmente se le chiusure sono nidificate o più chiusure in linea passeranno a una funzione in una riga. Quest'ultima cosa mi sembra più problematica. Poiché in questo caso si ottiene solo la linea iniziale e finale della riflessione, entrambe le funzioni si troveranno su tale linea e non si disporrà di informazioni utili per decidere quale di esse deve essere scaricata. Finora, non ho trovato una soluzione per questo, anche io non sono sicuro se c'è una soluzione.

Tuttavia, nella maggior parte dei casi, dovrebbe essere utile almeno per il debug, purché non ci si faccia affidamento. Feel free to enhance it!

+0

Come è possibile valutare il codice risultato dopo la modifica, senza utilizzare eval()? – Omranic

+0

Cosa intendi con * dopo la modifica *? – hek2mgl

+0

So che questo è vecchio, ma è ancora un caso per me .. Beh, dopo la modifica significa che ho preso il codice di chiusura riflesso, rimosso alcune linee e aggiunto altre, e dal momento che ora è solo una stringa, ho bisogno di valutare il codice modificato risultante senza l'utilizzo di eval() – Omranic

Problemi correlati