eval()
La funzione eval() in PHP valuta una string come codice PHP a runtime. È utile quando occorre eseguire codice PHP in modo dinamico.
Introduzione alla funzione eval()
La funzione eval() valuta una string come codice PHP e la esegue a runtime — nel momento in cui lo script raggiunge la chiamata eval(). Invece di scrivere codice che il parser PHP compila in anticipo, si passa a eval() una string che viene compilata ed eseguita al volo.
Questo rende eval() uno dei costrutti più potenti — e più pericolosi — del linguaggio. Questa pagina ne illustra la sintassi, i valori restituiti, i rari casi in cui è genuinamente utile, i rischi di sicurezza che ne fanno un'ultima risorsa, e le alternative più sicure a cui ricorrere per prime.
eval()è un costrutto del linguaggio, non una funzione ordinaria. Non è possibile chiamarla indirettamente tramite il nome di una funzione variabile né passarla a funzioni callback.
Sintassi
eval(string $code): mixedL'unico argomento è una string di codice PHP. Alcune regole importanti:
- Non includere il tag di apertura
<?php. La string è già trattata come sorgente PHP, quindi aggiungere<?phpfarebbe tornare in "modalità HTML". - Il codice deve essere sintatticamente valido e terminato correttamente. Un punto e virgola mancante o una parentesi graffa non chiusa produce un errore di analisi. Da PHP 7, un errore di analisi all'interno di
eval()lancia un'eccezioneParseErrorcatturabile — le versioni precedenti restituivanofalse.
Valore restituito
Il modo in cui eval() restituisce un valore dipende da ciò che fa il codice valutato:
- Se il codice esegue un'istruzione
return,eval()restituisce quel valore. - Altrimenti restituisce
null.
<?php
$result = eval('return 2 + 3;');
echo $result; // 5Ecco perché un return all'interno di eval() termina soltanto la string valutata, non l'intero script — il controllo torna alla riga successiva a eval(). Consulta l'istruzione return per il comportamento di return nelle funzioni normali.
Esempio di base
Ecco l'utilizzo più semplice possibile — costruire una string di codice ed eseguirla:
La variabile $code contiene PHP valido che stampa Hello, world!. eval() compila ed esegue quella string a runtime, quindi il messaggio viene visualizzato. Si noti che all'interno della string non è presente il tag <?php.
Gestione sicura degli errori
Poiché il codice non valido lancia un ParseError, è consigliabile racchiudere il codice non attendibile o generato dinamicamente in un blocco try/catch, in modo che una string errata non faccia crashare l'intera richiesta:
<?php
try {
eval('echo "missing semicolon"'); // no terminating ;
} catch (ParseError $e) {
echo "Could not evaluate: " . $e->getMessage();
}Questo stampa un messaggio "Could not evaluate" invece di un errore fatale, permettendo allo script di continuare.
Quando usare eval()?
Nel PHP moderno, quasi mai — e questa è la risposta onesta. I casi d'uso legittimi e circoscritti includono:
- Motori di template/espressioni che compilano un mini-linguaggio personalizzato in PHP (Twig e Blade fanno qualcosa di concettualmente simile, ma con un pesante sandboxing).
- Caching di configurazione compilata come PHP da eseguire in seguito con
eval, anche se scrivere un vero file.phpe usareincludeè più veloce e sicuro. - Strumenti educativi o di debug come i REPL, dove l'input è completamente attendibile.
Se il valore da calcolare è un dato (numeri, JSON, un elenco di opzioni), quasi certamente non è necessario usare eval().
Rischi di sicurezza
eval() esegue qualsiasi cosa le venga passata. Se qualsiasi parte della string può essere influenzata dall'input dell'utente, un attaccante può eseguire codice arbitrario — leggere file, cancellare dati o prendere il controllo del server. Questa è una classica vulnerabilità di remote code execution (RCE).
<?php
// NEVER do this:
$expr = $_GET['expr']; // attacker-controlled
eval("\$answer = $expr;"); // attacker can inject any PHPUna richiesta come ?expr=1; system('rm -rf /') eseguirebbe il comando iniettato. Considera ogni eval() su input utente come un exploit garantito.
Alternative più sicure
Prima di ricorrere a eval(), verifica se una di queste opzioni soddisfa le tue esigenze:
| Obiettivo | Usa invece di eval() |
|---|---|
| Analizzare dati strutturati | json_decode() |
| Chiamare una funzione scelta a runtime | Callback / funzioni variabili |
| Eseguire codice memorizzato in un file | include / require |
| Associare una string a un comportamento | Un match/switch o un array di closure |
| Valutare espressioni matematiche | Una libreria dedicata per il parsing di espressioni |
Conclusione
eval() valuta una string come codice PHP a runtime, restituendo il risultato di un'istruzione return al suo interno oppure null. È genuinamente potente, ma è anche una delle principali fonti di vulnerabilità di sicurezza — qualsiasi input controllato dall'utente passato ad essa costituisce un bug di remote code execution. Usala solo quando l'input è completamente attendibile e nessun costrutto integrato è adatto, racchiudila in un try/catch per ParseError, e preferisci le alternative più sicure illustrate sopra ogni volta che è possibile.