In PHP, dove tra l'altro non ci sono dichiarazioni di variabili, le regole
di scoping (o visibilità delle variabili) sono leggermente diverse da
quelle del linguaggio C o del Pascal.
Lo scope (ambito di visibilità) di una variabile è il contesto in cui
questa è definita. Di default tutte le variabili in PHP hanno uno scope
singolo.
Una variabile usata al di fuori di una funzione ha scope globale e basta e
non è disponibile di default all'interno di una funzione definita
dall'utente, perchè lo scope globale non è ereditato implicitamente dalle
funzioni come in C. Questa è una misura di sicurezza per impedire che per
errore una funzione definita dall'utente cambi inavvertitamente il valore
di una variabile globale. Quindi quando usate una variabile all'interno di
una funzione viene ricercata per default solo nello scope locale della
funzione, mentre in C viene cercata prima nello scope locale e poi, se non
vi è trovata, viene implicitamente ricercata nello scope globale. Tutte le
variabili globali sono accessibili ad una funzione C se dichiarate o
definite prima della funzione, anche se la loro definizione o dichiarazione
è esterna alla funzione stessa.
$a = 1; /* global scope */
Function Test () {
echo $a; /* riferimento ad una variabile nello scope locale */
}
Test (); // non stampa niente, $a non è settata nello scope locale
Il programma precedente non stampa niente, perchè $a viene ricercata solo
nello scope locale, dove non è settata. In C invece una variabile globale
come $a, definita o dichiarata prima di una funzione, oppure dichiarata
all'interno di una funzione (come variabile extern) è automaticamente
disponibile alla funzione, a meno che non venga mascherata da una
definizione locale con lo stesso nome. I programmatori C sappiano che
devono utilizzare sempre l'equivalente di extern del C in PHP, che è il
costrutto global, all'interno delle funzioni per importare variabili dallo
scope globale in quello locale se intendono utilizzarle; poichè lo scope
globale non viene ereditato nello scope locale, global è sempre necessaria
per accedere a variabili globali nello scope locale.
$a = 1; /* global scope */
Function Test () {
global $a;
echo $a; /* riferimento ad una variabile nello scope globale */
}
Test (); // stampa 1
Nel caso dobbiate accedere a più variabili, basta specificarne la lista
separata da virgole nel costrutto global, anziché usare più costrutti
global:
global var1, var2, ..., varn;
Naturalmente purchè la variabile globale venga settata prima della chiamata
della funzione, la funzione non ha problemi a vederla:
Function Test () {
global $a;
echo $a; /* riferimento ad una variabile nello scope globale */
}
$a = 1; /* global scope */
Test (); // stampa 1
################################################## #####
Function Test () {
global $a;
echo $a; /* riferimento ad una variabile non settata nello scope globale */
}
Test (); // non stampa niente
$a = 1; /* global scope */
Un'alternativa all'utilizzo del costrutto global per accedere a variabili
globali da uno scope locale consiste nell'uso dell'array (associativo)
$GLOBALS. In pratica in uno scope locale PHP importa di default un array
associativo globale in cui memorizza tutti i riferimenti alle variabili
globali create dal programma; in effetti quando si importa una variabile
con:
global $var;
questo equivale a creare un riferimento ad un elemento omonimo dell'array
$GLOBALS:
$var =& $GLOBALS["var"];
Questo array contiene le coppie nome=>valore di tutte le variabili globali,
quindi l'esempio precedente si può riscrivere in questo modo:
$a = 1; /* global scope */
Function Test () {
echo $GLOBALS["a"]; /* riferimento ad una variabile nello scope globale */
}
Test (); // stampa 1
Le variabili con scope locale sono normalmente disallocate dall'interprete
quando l'interpretazione di una funzione finisce, allo scopo di
economizzare lo spazio di memoria, così ogni volta che viene chiamata una
funzione, una variabile locale presenta un valore non settato.
Poniamo il caso in cui si debba utilizzare una variabile solamente
all'interno di una funzione e si voglia che il suo valore venga conservato
tra una chiamata e l'altra della funzione, come nel caso banale di una
funzione che conta il numero di volte che è stata chiamata. Una possibile
soluzione è utilizzare allo scopo una variabile globale ed importarla nello
scope locale con global:
function counts_itself()
{
global $i;
return ++$i;
}
echo counts_itself(); // stampa 1
echo counts_itself(); // stampa 2
echo counts_itself(); // stampa 3
Questo metodo funziona, ma presenta l'inconveniente che la variabile,
avendo scope globale, può essere accidentalmente alterata da codice
presente in questo scope e persino da funzioni che per sbaglio la
importino. Il nome scelto per la variabile è così comune come valore indice
che quasi certamente la variabile è esposta a questo rischio.
La soluzione consiste nel conferirle scope locale, ma tempo di vita
(lifetime) globale tramite una dichiarazione static, che è del tutto
analoga a quella del C:
function counts_itself()
{
static $i=0;
return ++$i;
}
echo counts_itself(); // stampa 1
echo counts_itself(); // stampa 2
echo counts_itself(); // stampa 3
In PHP non è necessario inizializzare la variabile scrivendo =0 dopo static
$i, ma è comunque bene farlo per ragioni di chiarezza del codice. In questo
modo si può avere una variabile globale $i che non avrà niente a che fare
con la $i vista da counts_itself e nello stesso tempo far sì che
quest'ultima sia permanente per tutta la durata del programma.