[Ezt a fejezetet érdemes elolvasni, még akkor is, ha profi vagy valamilyen programozási nyelvben, mert a PHP tartogat egy-két érdekes meglepetést...]
A változó hatásköre az a környezet, amelyben a változó definiált. A legtöbb esetben minden PHP változónak egyetlen hatásköre van. Ez az egyetlen hatáskör kiterjed az include és a require segítségével használt fájlokra is. Például:
Itt az $a változó elérhető lesz az beillesztett b.inc szkriptben is. A felhasználói függvényekkel a lokális függvényhatáskör kerül bevezetésre. Alapértelmezés szerint minden, függvényen belül használt változó ebbe a lokális függvényhatáskörbe tartozik, például:
<?php |
Ez a szkript nem fog semmilyen kimenetet sem eredményezni, mivel az echo kifejezés az $a változónak egy helyi - függvényen belüli - változatára utal, és ebben a hatáskörben ehhez nem rendeltek értéket. Ez valamelyest különbözik a C nyelv filozófiájától, ahol a globális változók automatikusan elérhetők bármely függvényből, feltéve ha a függvényben újra nem definiáltad azt a változót. Ez 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 kell deklarálni a függvényekben.
Először nézzünk egy példát a global használatára:
A fenti szkript 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ötve, hány globális változót kezelhet egy függvény.
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ával egyenértékű megoldás:
A $GLOBALS asszociatív tömb, ahol a globális változó neve jelenti a kulcsot, és a változó értéke a tömbelem értéke. Vedd észre, hogy a $GLOBALS tömb minden hatáskörben létezik, mivel a $GLOBALS egy szuperglobális változó. A következő példa a szuperglobális változók erejét szemlélteti.
A változók hatáskörének másik fontos lehetősége a static (statikus) változó. A 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 veszti el az értékét, a változó hatásköréből való kilépés esetén is megmarad az értéke:
Ez nagyon haszontalan függvény, mivel 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++ teljesen felesleges, mert amint vége a függvény futásának az $a változó megszűnik. Ahhoz, hogy ebből értelmes számlálófüggvény legyen - megmaradjon a számláló értéke -, az $a változót statikusnak kell deklarálni:
Most már valahányszor meghívódik a Test() függvény, kiírja $a értékét, majd azt megnöveli eggyel.
A statikus változókat a rekurzív függvények megvalósításában is felhasználhatjuk. Rekurzívnak nevezzük azt a függvényt, amely saját magát hívja meg. Ezt természetesen feltételhez kell kötni, nehogy végtelen rekurzióba kerüljön a vezérlés és meghatározatlan időre a függvényen belül csapdába esik. Mindig meg kell bizonyosodni arról, hogy megfelelő feltétel rendelkezésre áll a rekurzió befejezéséhez. A következő függvény rekurzívan elszámol 10-ig a statikus $count változó segítségével: [A static kulcsszó nagyon fontos!]
Megjegyzés: Statikus változókat a fenti példákban szereplő módon lehet deklarálni. Ha olyan értéket próbálsz értékül adni neki, amely egy kifejezés eredménye, az parse error-t fog okozni.
A PHP 4-et működtető Zend Engine 1, a statikus és globális változó módosítókat referenciákkal implementálja. Például egy valódi globális változó beemelve egy függvény hatáskörébe a global utasítással tulajdonképpen létrehoz egy referenciát a globális változóhoz. Ez váratlan viselkedésmódhoz vezethet, amelyet a következő példa illusztrál:
<?php |
A példában szereplő kód végrahajtása a következő kimenetet produkálja:
NULL object(stdClass)(0) { } |
Hasonló viselkedésmód jellemzi a static utasítást. A referenciák nem statikusan vannak tárolva:
<?php |
A példa végrehajtása a következő kimenetet eredményezi:
Statikus objektum: NULL Statikus objektum: NULL Statikus objektum: NULL Statikus objektum: object(stdClass)(1) { ["property"]=> int(1) } |
A példa azt szemlélteti, hogy amikor hozzárendelsz egy referenciát egy statikus változóhoz, az nem lesz megjegyezve amikor újra meghívod a &get_instance_ref() függvényt.