Aikido

Perché è meglio evitare i nomi di variabili dinamici in PHP

Leggibilità

Regola
Evita le variabili dinamici
Variabile nomi nomi (variabili variabili) possono portare
a difficoltà da da mantenere codice e comportamento . 
Il loro utilizzo è di solito il risultato di un errore di battitura.

Lingue supportate: PHP

Introduzione

La funzionalità delle "variabili variabili" di PHP consente di utilizzare il valore di una variabile come nome di un'altra variabile con il $$ sintassi. Quella che sembra una scorciatoia ingegnosa si trasforma in un incubo per il debug quando non è possibile determinare in modo statico quali variabili esistano o quale sia il loro contenuto. Il codice che utilizza $$userName L'uso di una proprietà di array o oggetto rende impossibile agli IDE fornire il completamento automatico, agli analizzatori statici individuare i bug e agli sviluppatori tracciare il flusso dei dati all'interno dell'applicazione.

Perché è importante

Manutenibilità del codice: le variabili variabili compromettono il funzionamento di tutti gli strumenti su cui fanno affidamento gli sviluppatori. Gli IDE non sono in grado di completare automaticamente i nomi delle variabili, individuarne gli utilizzi o eseguire il refactoring in modo sicuro. Gli strumenti di analisi statica non riescono a rilevare variabili non definite o discrepanze di tipo. Il debug richiede un’ispezione in fase di esecuzione, poiché non è possibile effettuare ricerche nel codice per individuare i punti in cui le variabili vengono impostate o lette.

Implicazioni in materia di sicurezza: Quando i nomi delle variabili provengono dall’input dell’utente, gli aggressori possono sovrascrivere variabili arbitrarie, comprese quelle critiche per la sicurezza. Un parametro di richiesta dannoso potrebbe prendere di mira $$_GET['var'] per sovrascrivere $isAdmin, $userId, oppure variabili di sessione. Ciò crea vulnerabilità legate all’iniezione di variabili che sono difficili da individuare e facili da sfruttare.

Impatto sulle prestazioni: le variabili variabili costringono PHP a eseguire ricerche in fase di esecuzione anziché la risoluzione dei simboli in fase di compilazione. L'interprete deve valutare dinamicamente il nome della variabile ad ogni accesso, impedendo così le ottimizzazioni che funzionano con le variabili normali. Gli array e gli oggetti offrono funzionalità simili con prestazioni migliori.

Esempi di codice

❌ Non conforme:

function processFormData($formType) {
    $userForm = ['name' => '', 'email' => ''];
    $adminForm = ['name' => '', 'email' => '', 'role' => ''];

    $formName = $formType . 'Form';
    $$formName = array_merge($$formName, $_POST);

    if ($$formName['email']) {
        sendEmail($$formName['email']);
    }

    return $$formName;
}

// What variable does this actually use?
processFormData('user');

Perché è sbagliato: Il codice crea $userForm oppure $adminForm in modo dinamico utilizzando $$formName, rendendo impossibile individuare quale variabile venga modificata. Se $formType poiché deriva dall'input dell'utente, gli aggressori potrebbero inserire nomi di variabili arbitrari per sovrascrivere variabili critiche.

✅ Conforme:

function processFormData(string $formType): array {
    $forms = [
        'user' => ['name' => '', 'email' => ''],
        'admin' => ['name' => '', 'email' => '', 'role' => '']
    ];

    if (!isset($forms[$formType])) {
        throw new InvalidArgumentException('Invalid form type');
    }

    $form = array_merge($forms[$formType], $_POST);

    if (!empty($form['email'])) {
        sendEmail($form['email']);
    }

    return $form;
}

// Clear which data structure is being used
processFormData('user');

Perché è importante: il codice utilizza un array esplicito con chiavi note, rendendo chiaro il flusso dei dati e consentendo di sfruttare tutte le funzionalità dell'IDE. La convalida degli input previene gli attacchi di tipo "injection", mentre l'analisi statica permette di verificare la correttezza del codice.

Conclusione

Sostituisci le variabili variabili con array, oggetti o una struttura del codice più adeguata. Utilizza gli array quando hai bisogno di un accesso dinamico alle chiavi, ricorri agli oggetti per i dati strutturati con proprietà note e rifattorizza la logica duplicata in astrazioni appropriate. Le variabili variabili indicano quasi sempre un problema di progettazione che strutture dati adeguate risolverebbero in modo più chiaro.

Domande frequenti

Hai delle domande?

Esistono usi legittimi delle variabili variabili?

Estremamente rari. Talvolta vengono utilizzati nei motori di template e nei framework di metaprogrammazione, ma anche in quei casi è preferibile ricorrere ad array o a strutture dati dedicate. Se pensi di aver bisogno di variabili variabili, probabilmente ti serve un array con chiavi dinamiche oppure una riprogettazione del tuo flusso di dati.

E che dire della funzione `extract()`, che crea variabili in modo dinamico?

Evita di usare `extract()` per gli stessi motivi per cui è consigliabile evitare le variabili variabili. Questa funzione crea variabili in modo dinamico a partire dalle chiavi di un array, compromettendo l'analisi statica e generando rischi per la sicurezza. Utilizza direttamente l'accesso all'array: `$data['key']` invece di `extract($data); $key`. Nel codice PHP moderno, l'uso di `extract()` dovrebbe essere considerato un "code smell".

Come posso rifattorizzare il codice esistente che utilizza variabili variabili?

Identifica il modello che stai implementando. Di solito si tratta di dati di configurazione (usa gli array), proprietà dinamiche (usa oggetti o array) o logica condizionale (usa strutture di controllo adeguate). Nella maggior parte dei casi, sostituisci $$varName con $config[$varName]. Usa gli oggetti quando hai bisogno di sicurezza dei tipi e del supporto dell'IDE per l'accesso alle proprietà.

E se si usassero variabili variabili per le costanti?

Rimane comunque un problema. Se devi accedere dinamicamente alle costanti, usa `constant($name)`, anche se questo indica un problema di progettazione. Un approccio migliore: raggruppa le costanti correlate in una classe e usa un array o un'espressione `match` per selezionare il valore appropriato in base alle condizioni di esecuzione.

Le variabili variabili possono causare conflitti tra spazi dei nomi?

Sì, soprattutto con le variabili superglobali e quelle del framework. Il codice che utilizza $$type = 'value' potrebbe creare accidentalmente variabili come $_GET, $_POST o variabili del framework come $this in contesti inaspettati. Gli array organizzano naturalmente i propri dati in spazi dei nomi, evitando tali conflitti per come sono progettati.

Metti in sicurezza ora

Metti in sicurezza il tuo codice, il cloud e il runtime in un unico sistema centralizzato.
Trova e risolvi le vulnerabilità rapidamente e automaticamente.

Nessuna carta di credito richiesta | Risultati della scansione in 32 secondi.