Változók hatásköre

[Ezt a fejezetet érdemes elolvasnod, még akkor is, ha profi vagy valamilyen programozási nyelvben, mert a PHP tartogat egy-két érdekes meglepetést...]

Egy változó hatásköre az a környezet, amiben a változó definiált. A legtöbb esetben minden PHP változónak egy hatásköre van. Ez az egyetlen hatáskör kiterjed az include és a require segítségével használt file-okra is. Például:

  1 
  2 
  3 $a = 1;
  4 include "b.inc";
  5 
  6     

Itt az $a változó elérhető lesz az include-olt b.inc scriptben is. Felhasználói függvényeken belül egy lokális függvényhatáskör lép érvénybe. Minden egyes függvényen belül használt változó csak azon a bizonyos függvényen belülre van korlátozva. Például:

  1  
  2 
  3 $a = 1; /* globális hatáskör */ 
  4 
  5 Function Test () { 
  6     echo $a; /* egy helyi változót vár */ 
  7 } 
  8 
  9 Test ();
 10 
 11     

Ez a script nem fog semmilyen kimenetet sem eredményezni, mivel az echo kifejezés az $a változónak egy helyi változatára utal, és ehhez még nem került hozzárendelésre érték abban a hatáskörben. Bizony, bizony, ez egy "kicsit" különbözik a C nyelv filozófiájától, ahol egy globális változó automatikusan elérhető bármely függvényből, feltéve ha a függvényben újra nem definiáltad azt a változót. Ez bizony problémák forrása lehet, ha az ember véletlenül megváltoztat egy globális változót. A PHP-ben a globális változókat global kulcsszóval deklarálni kell a függvényekben, ha szeretnénk őket a függvényben használni. Például:

  1 
  2 
  3 $a = 1;
  4 $b = 2;
  5 
  6 Function Osszead () {
  7     global $a, $b;
  8 
  9     $b = $a + $b;
 10 } 
 11 
 12 Ossszead ();
 13 echo $b;
 14 
 15     

A fenti script kiírja, hogy "3". $a és $b global-ként való deklarálásával minden utalás ezekre a változókra a globális változót fogja érinteni. Nincs megkötés arra, hogy hány globális változó hatáskörét lehet "becsempészni" a függvénybe.

Globális változók elérésének másik módja a PHP által definiált speciális $GLOBALS tömb használata. Az előbbi példát így is meg lehetett volna írni:

  1 
  2 
  3 $a = 1;
  4 $b = 2;
  5 
  6 Function Osszead () {
  7     $GLOBALS["b"] = $GLOBALS["a"] + $GLOBALS["b"];
  8 } 
  9 
 10 Osszead ();
 11 echo $b;
 12 
 13     

A $GLOBALS tömb egy asszociatív tömb, ahol a globális változó neve a kulcs, és a változó az értéke.

Egy másik fontos tulajdonsága a változók hatáskörének a static (statikus) változó. Egy statikus változó csak lokális hatáskörben él - egy függvényen belül, de két függvényhívás közt nem felejti el az értékét (pontosabban megfogalmazva a változó hatásköréből való kilépés esetén is megmarad az értéke). Figyeld csak:

  1 
  2 
  3 Function Test () { #ezt nem Function Body-ból fordítottam...
  4     $a = 0;
  5     echo $a;
  6     $a++;
  7 }
  8 
  9     

Ez egy veszettül haszontalan hülye függvény, ami nem csinál mást, mint minden meghívásakor $a-t 0-ra állítja, aztán kiírja a 0-t. Az $a++ meg teljesen felesleges, mert amint vége a függvénynek, az $a változót tároló bitek felveszik a néhai előnevet. Ahhoz, hogy egy értelmes számolást tudjunk végezni, és megmaradjon a számláló értéke, az $a változót statikusnak kell deklarálni:

  1 
  2 
  3 Function Test () {
  4     static $a = 0;
  5     echo $a;
  6     $a++;
  7 }
  8 
  9     

Most, valahányszor meghívódik a Test() függvény, kiírja $a-t, majd megnöveli eggyel.

A statikus változók biztosítanak egy módot, hogy a rekurzív függvényekkel bánjunk. Rekurzív az a függvény, amely saját magát meghívja [persze jobb esetben illik feltételhez kötni, különben a szótárban nem úgy fog szerepelni, hogy Rekurzió: ld. rekurzió, hanem úgy, hogy Rekurzió = Stack overflow]. Szóval csak óvatosan azokkal a rekurzív függvényekkel, nehogy végtelen rekurzióba kerüljünk. Ezért kell a feltétel, mert az fogja leállítani a rekurziót. A következő függvény rekurzívan elszámol 10-ig a statikus $count változó segítségével. [Ki ne felejtsd a static kulcsszót, mert akkor nagy baj lesz!]:

  1 
  2 
  3 Function Test () {
  4     static $count = 0;
  5 
  6     $count++;
  7     echo $count;
  8     if ($count < 10) {
  9         Test ();
 10     }
 11     $count--;
 12 }
 13 
 14