[PILLOLE PHP] Lo scope

Un argomento che può risultare ostico al pricipiante (o che perlomeno può indurlo a commettere degli errori banali o a perdere tempo) é senz’altro lo scope, ovvero l’ambito di validità di una variabile. Nell’esecuzione di uno script infatti una variabile potrebbe avere diversi significati a dipendenza di dove viene dichiarata..
Iniziamo dunque a vedere quali sono i tre possibili scope di una variabile:

  • Globale: una variabile si dice globale quando é dichiarata nello script principale (all’interno delle funzioni non avrà nessun valore);
  • Locale: si dice locale una variabile dichiarata all’interno di una funzione (all’esterno della funzione non avrà nessun valore);
  • Super-globale: le variabili super-globali sono quelle gestite da PHP ($_SESSION, $_SERVER, $_POST, $_GET, $_REQUEST, $_COOKIE, $_ENV, $_FILES, $GLOBALS). L’ambito di validità delle variabili super-globali é totale, cioé sono valide sia all’interno che all’esterno delle funzioni. Inoltre va considerato che anche le costanti hanno un abito di validità super-globale.

Ma facciamo subito degli esempi.

Le variabili globali non sono disponibili in ambito locale

Come abbiamo già detto, le variabili globali non sono disponibili in ambito locale.
Guarda l’esempio spiegato di seguito:

$var = “Hello”; // $var é dichiarata in abito globale

function Test()
{
    // alla funzione Test() si richiede si stampare $var
    // ma siamo all’interno di una funzione
    // che non ha accesso alle variabili globali
    echo $var;
}

// di conseguenza, invocando la funzione Test()
// verrà sollevato un errore ($var non é definita)
Test();

Le variabili locali non sono disponibili in ambito globale

Analizziamo l’esempio che segue per capire cosa intendiamo quando diciamo che le variabili locali non sono disponibili in ambito globale:

function Test()
{
    //La funzione Test() ha lo scopo di valorizzare la variabile $var
    $var = "Hello";
}

// Invocando la funzione Test(), $var viene valorizzata
// ma solo in ambito locale
Test();

// dunque tentare di stamparla a video
// in ambito globale produrrà un errore
// $var non risulta definita
echo $var;

Quindi riassumendo possiamo dire che una funzione, per quanto concerne le variabili, é chiusa ermeticamente rispetto al resto del codice.

Le variabili super-globali sono disponibili ovunque

Adesso, andiamo a dare uno sguardo alle variabili super-globali:

define('MIA_COSTANTE', 'Hello');

function Test()
{
    echo MIA_COSTANTE . ': MIA_COSTANTE in ambito locale<br />';
    echo $_SERVER['PHP_SELF'] . ': PHP_SELF in ambito locale<br />';
}

Test();

echo MIA_COSTANTE . ': MIA_COSTANTE in ambito globale<br />';
echo $_SERVER['PHP_SELF'] . ': PHP_SELF in ambito globale';

//Il risultato sarà
// Hello: MIA_COSTANTE in ambito locale
//test.php: PHP_SELF in ambito locale
//Hello: MIA_COSTANTE in ambito globale
//test.php: PHP_SELF in ambito globale

Come far cadere le barriere tra ambito globale ed ambito locale?

E’ possibile fare in modo che una variabile globale sia resa disponibile anche all’interno di una funzione tramite la keyword global; vediamo come:

// $var é dichiarata in ambito globale
$var = "Hello";

function Test()
{
    // Nella funzione Test() dichiaro di voler
    // utilizzare la variabile globale $var
    global $var;

    // Ora $var é disponibile e può essere utilizzata
    $var .= " World";
}

Test();

// Verrà stampato "Hello World"
echo $var;

E’ possibile ottenere lo stesso risultato utilizzando l’array $GLOBALS, difatti l’array $GLOBALS è una variabile automaticamente disponibile in tutti gli ambiti senza doverla dichiarare globale per accedervi dall’interno di una funzione.

$var = "Hello";

function Test()
{
    $GLOBALS['var'] .= " World";
}

Test();
echo $var;

Considera comunque che rompere gli argini tra ambito locale ed ambito globale é un’operazione da evitare finché é possibile.

Perché l’utilizzo di global é da evitare?

Come detto, per quanto possibile, é meglio evitare l’utilizzo delle tecniche appena descritte.
La netta distinzione di ambiti tra il locale e il globale, che al profano può sembrare un’inutile seccatura, ha delle ragioni molto precise.
Le funzioni generalmente rappresentano una parte di codice molto specifica della quale intravvediamo spesso dei possibili riutilizzi.
Dal momento che:

  1. non sappiamo quando e in che circostanza potrebbe tornarci utile questa funzione;
  2. nel caso in cui stiamo lavorando in team ad un grande progetto, potrebbe anche accadere che questa funzione venga riutilizzata da qualcun’altro;

è bene che la funzione sia il più robusta possibile. Global inevitabilemente introduce delle ambiguità e potrebbe portare all’interno della funzione dei valori non corretti.
Una funzione invece, di principio, riceve i dati come argomenti e li restituisce attraverso la keyword return. E questo basta per garantirle la robustezza che auspichiamo.

Per concludere vediamo come passare correttamente gli argomenti ad una funzione.

Argomenti, argomenti facoltativi, argomenti arbitrari

Vediamo brevemente e in pratica come passare gli argomenti ad una funzione in tre diversi casi.

SOMMA DI DUE NUMERI

function Somma($a,$b)
{
    return $a + $b;
}

echo Somma(5,9);

SOMMA DI DUE O TRE NUMERI (argomenti facoltativi)

//il terzo parametro ($c) lo dichiariamo come
//uguale a 0. In questo modo se non verrà inserito
//nulla avrà valore 0 e non influirà sulla somma
//mentre se passeremo anche il terzo argomento
//questo andrà a sovrascrivere la variabile $c

function Somma($a,$b,$c = 0)
{
    return $a + $b + $c;
}

echo Somma(6,2);
echo Somma(5,9,6);

SOMMA DI X NUMERI (argomenti arbitrari)

function Somma()
{
    $args = func_get_args();
    $return = 0;
    foreach($args as $value)
    {
         $return = $return + $value;
    }
    return $return;
}

echo Somma(2,3,4,5,9,0,0,2);

Conclusione

In questo articolo abbiamo visto alcune caratteristiche fondamentali del liguaggio. La logica degli ambiti di validità delle variabili riveste infatti una notevole importanza nello sviluppo di un codice robusto. Spero di aver chiarito questo argomento che, come ho detto all’inizio, risulta spesso essere un punto critico per i principianti.

Tag: ,

L'autore

Maurizio è sposato con la triade PHP - MySql - Apache e, non pago, ha un'amante chiamata jQuery. Ha un blog dove cerca di descrivere nei minimi particolari sia la moglie che l'amante. La sua vera specialità è la realizzazione di gestionali complessi anche se non rifiuta mai un sito web. +

Sito web dell'autore | Altri articoli scritti da

Articoli correlati

Potresti essere interessato anche ai seguenti articoli:

15 commenti

Trackback e pingback

  1. Raccolta di articoli della settimana 12-19/06/2011 | Saverio Gravagnola
    [...] scope in PHP (Your Inspiration [...]