Introduzione
In PHP, le superglobali sono variabili disponibili in qualsiasi punto dello script, anche dentro funzioni e metodi, senza doverle dichiarare con la parola chiave global. Tra queste variabili c’è $GLOBALS, un array associativo che contiene tutti i nomi delle variabili globali definite nello script.
$GLOBALS può essere utile in piccoli script procedurali, negli strumenti di diagnostica e durante il refactoring di codice legacy. Tuttavia, usarla per condividere liberamente dati tra tutte le funzioni può rendere l’applicazione difficile da comprendere e testare. Per questo motivo è importante conoscerne il funzionamento, ma anche applicare alcune regole per limitarne gli effetti collaterali.
In questo tutorial costruiremo un semplice contatore globale, lo aggiorneremo da una funzione e analizzeremo un approccio più ordinato basato sul passaggio esplicito dei parametri.
Codice completo
<?php
declare(strict_types=1);
/*
* Variabile globale inizializzata nel contesto principale dello script.
* Sarà accessibile anche tramite $GLOBALS[´contatore´].
*/
$contatore = 0;
/*
* Elenco globale delle operazioni eseguite.
* È preferibile mantenere una struttura dati ben definita,
* invece di creare molte variabili globali indipendenti.
*/
$registroOperazioni = [];
/**
* Incrementa il contatore usando la superglobale $GLOBALS.
*
* @param int $quantita Numero di unità da aggiungere
*/
function aggiungiOperazioni(int $quantita): void
{
if ($quantita < 1) {
throw new InvalidArgumentException(
´La quantità deve essere maggiore di zero.´
);
}
// Accesso diretto alla variabile globale tramite il suo nome.
$GLOBALS[´contatore´] += $quantita;
// Aggiornamento di un secondo valore globale.
$GLOBALS[´registroOperazioni´][] = [
´quantita´ => $quantita,
´totale´ => $GLOBALS[´contatore´],
];
}
/**
* Restituisce un riepilogo dello stato globale.
*
* @return array<string, mixed>
*/
function creaRiepilogo(): array
{
return [
´totale´ => $GLOBALS[´contatore´],
´operazioni´ => count($GLOBALS[´registroOperazioni´]),
];
}
try {
aggiungiOperazioni(3);
aggiungiOperazioni(2);
$riepilogo = creaRiepilogo();
echo ´<h1>Riepilogo operazioni</h1>´;
echo ´<p>Totale: ´ . $riepilogo[´totale´] . ´</p>´;
echo ´<p>Operazioni registrate: ´ .
$riepilogo[´operazioni´] . ´</p>´;
echo ´<pre>´;
echo htmlspecialchars(
print_r($GLOBALS[´registroOperazioni´], true),
ENT_QUOTES,
´UTF-8´
);
echo ´</pre>´;
} catch (InvalidArgumentException $exception) {
echo ´Errore: ´ . htmlspecialchars(
$exception->getMessage(),
ENT_QUOTES,
´UTF-8´
);
} Spiegazione
Come funziona $GLOBALS
Quando definiamo una variabile fuori da una funzione, questa appartiene allo scope globale dello script. Una funzione, però, possiede normalmente un proprio scope locale e non può usare direttamente quella variabile.
Per esempio, questo codice non funziona come spesso si potrebbe immaginare:
<?php
$totale = 10;
function mostraTotale(): void
{
// $totale non è disponibile automaticamente qui.
echo $totale;
} Con $GLOBALS, invece, possiamo accedere alla variabile usando il suo nome come chiave:
<?php
$totale = 10;
function mostraTotale(): void
{
echo $GLOBALS[´totale´];
}
mostraTotale(); // Stampa 10 È importante ricordare che $GLOBALS[´totale´] e la variabile $totale fanno riferimento allo stesso valore globale. Se modifichiamo il primo, modifichiamo anche il secondo.
Confronto con la parola chiave global
Un’alternativa è dichiarare la variabile con global all’interno della funzione:
<?php
$messaggio = ´Operazione completata´;
function stampaMessaggio(): void
{
global $messaggio;
echo $messaggio;
} Le due tecniche hanno un risultato simile, ma $GLOBALS rende esplicito il fatto che stiamo leggendo o modificando una variabile globale tramite un array. Questa caratteristica può essere utile in codice dinamico, ma non elimina i rischi legati allo stato condiviso.
Il problema delle modifiche imprevedibili
Se molte funzioni modificano le stesse chiavi di $GLOBALS, diventa difficile capire quale funzione abbia cambiato un valore. Inoltre, i test automatici possono diventare fragili perché una funzione potrebbe dipendere da dati lasciati da una precedente esecuzione.
Un approccio più sicuro consiste nel passare i dati come parametri e restituire un risultato:
<?php
function aggiungi(int $totale, int $quantita): int
{
if ($quantita < 1) {
throw new InvalidArgumentException(´Quantità non valida.´);
}
return $totale + $quantita;
}
$totale = aggiungi(0, 3);
$totale = aggiungi($totale, 2);
echo $totale; // 5 Best practice
- Limita l’uso di
$GLOBALS: preferisci parametri, valori restituiti e oggetti con responsabilità definite. - Usa nomi chiari: se devi accedere a una variabile globale, scegli chiavi descrittive come
configurazioneApporegistroOperazioni. - Non inserire dati provenienti direttamente dall’utente: una superglobale non rende automaticamente sicuri i valori contenuti.
- Evita di salvare segreti in variabili globali: password, token e chiavi private devono essere gestiti con particolare attenzione.
- Valida i dati prima di modificarli: nell’esempio controlliamo che la quantità sia un intero positivo.
- Proteggi l’output HTML: quando visualizzi dati dinamici, utilizza
htmlspecialchars()per ridurre il rischio di XSS. - Preferisci funzioni pure nei componenti riutilizzabili: una funzione che riceve input e restituisce output è più semplice da testare.
Riepilogo
$GLOBALS è una superglobale che permette di accedere alle variabili dello scope globale da qualunque funzione. È semplice da usare e può essere utile in script piccoli o durante la manutenzione di applicazioni legacy.
Il suo principale svantaggio è lo stato condiviso: più parti del programma possono leggere e modificare gli stessi dati, creando dipendenze nascoste. Nei progetti moderni è generalmente preferibile passare i valori tramite parametri, usare classi e mantenere le responsabilità ben separate.
