Zasięg zmiennych
Zasięg zmiennej zależy od miejsca, w jakim ją zdefiniowano.
Najczęściej zmienne PHP widoczne są tylko w jednym zasięgu.
Taki zasięg obejmuje również pliki dołączone funkcjami include i require. Na
przykład:
Tutaj zmienna $a będzie dostępna także wewnątrz dołączonego
funkcją include pliku b.inc w skrypcie. Jednakże wewnątrz
funkcji zdefiniowanych samodzielnie zmienne mają zasięg lokalny. Każda
zmienna użyta wewnątrz funkcji jest domyślnie ograniczona do zasięgu lokalnego
funkcji. Na przykład:
Ten skrypt nie wyświetli niczego, ponieważ instrukcja echo
odwołuje się do zmiennej lokalnej $a,
której jak dotąd nie została przypisana żadna wartość. Można
tu zauważyć różnicę w stosunku do języka C, gdzie
zmienne globalne są zawsze dostępne wewnątrz
definicji funkcji, o ile nie zostały nadpisane przez lokalną definicję
zmiennej. Może to spowodować problem, że ktoś może nieodwracalnie
zmienić wartość zmiennej globalnej. W PHP zmienne globalne muszą
być jawnie określone jako globalne wewnątrz funkcji, w której mają być użyte,
do czego używamy słowa kluczowego global.
Polecenie global
Najpierw, przykład użycia global:
Przykład #1 Używanie polecenia global
<?php
$a = 1;
$b = 2;
function suma()
{
global $a, $b;
$b = $a + $b;
}
suma();
echo $b;
?>
Powyższy skrypt wyświetli wynik 3. Przez zadeklarowanie
wewnątrz funkcji globalności zmiennych $a i
$b, wszystkie odwołania do tych zmiennych
będą odnosiły się do ich globalnych wersji. Nie ma żadnych ograniczeń
w ilości zmiennych globalnych, na których chcemy operować wewnątrz funkcji.
Drugim sposobem uzyskania dostępu do zmiennych globalnych wewnątrz funkcji
jest użycie specjalnej, zdefiniowanej przez PHP tablicy
$GLOBALS. Powyższy przykład można zatem przepisać tak:
Przykład #2 Używanie $GLOBALS zamiast polecenia global
<?php
$a = 1;
$b = 2;
function Suma()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
Suma();
echo $b;
?>
Tablica $GLOBALS jest asocjacyjną tablicą,
w której nazwa zmiennej jest kluczem, a zawartość zmiennej
wartością komórki tablicy.
Zauważ, że $GLOBALS jest dostępna z każdego miejsca,
ponieważ $GLOBALS jest tablicą superglobalną.
Poniżej przykład demonstrujący moc superglobali:
Przykład #3 Przykład demonstrujący superglobale i zasięg zmiennych
<?php
function test_global()
{
// Większość predefiniowanych zmiennych nie jest "super i wymaga
// 'global', by być dostępnymi w zasięgu lokalnym funkcji.
global $HTTP_POST_VARS;
echo $HTTP_POST_VARS['name'];
// Superglobale są dostępne z każdego miejsca
// i nie wymagają 'global'. Superglobale udostępniono
// wraz z PHP 4.1.0, a HTTP_POST_VARS jest
// uważane za przestarzałe.
echo $_POST['name'];
}
?>
Informacja:
Użycie global poza funkcją nie jest
błędem. Może on zostać użyty jeżeli plik jest dołączany z wnętrzna funkcji.
Używanie zmiennych statycznych
Jeszcze jedną ważną rzeczą, związaną z zasięgiem zmiennych jest zmienna
statyczna (ang. static variable). Zmienna statyczna
może mieć wyłącznie zasięg lokalny, ale nie traci swojej wartości, kiedy
program opuści ten zasięg lokalny, w którym dana zmienna statyczna się
znajduje. Rozważmy poniższy przykład:
Przykład #4 Przykład ukazujący przydatność zmiennych statycznych
<?php
function test()
{
$a = 0;
echo $a;
$a++;
}
?>
Ta funkcja jest bezużyteczna, gdyż przy każdym jej wywołaniu zmienna
$a otrzymuje wartość 0, w związku
z czym funkcja stale wyświetla 0. Występująca potem
inkrementacja $a++ nie ma żadnego znaczenia, gdyż
funkcja się kończy i zmienna $a znika. Aby powyższa
funkcja miała jakiś sens, należy zapobiec gubieniu wartości
$a, do czego używamy słowa kluczowego static:
Przykład #5 Przykład użycia zmiennych statycznych
<?php
function test()
{
static $a = 0;
echo $a;
$a++;
}
?>
Teraz, $a jest inicjowana tylko przy pierwszym wywołaniu funkcji
a, przy każdym wywołaniu funkcji test(), zostanie wyświetlona wartość
zmiennej $a, po czym ta zmienna zostanie inkrementowana.
Zmienne statyczne pozwalają też na wykorzystanie funkcji rekurencyjnych,
czyli takich, które wywołują same siebie. Funkcje rekurencyjne
należy pisać ostrożnie, gdyż łatwo jest wywołać nieskończoną
rekurencję. Musisz być pewny, że masz odpowiednie mechanizmy
do zatrzymania rekurencji w jakimś momencie. Poniższa, prosta
funkcja rekurencyjnie liczy do 10, używając zmiennej
statycznej $licznik, aby wiedzieć, kiedy się zatrzymać:
Przykład #6 Zmienne statyczne w funkcjach rekurencyjnych
<?php
function test()
{
static $licznik = 0;
$licznik++;
echo $licznik;
if ($licznik < 10) {
test();
}
$licznik--;
}
?>
Informacja:
Zmienne statyczne mogą być deklarowane, tak jak w powyższym przykładzie.
Od PHP 5.6 można przypisać wartości do tego typu zmiennych, poprzez wynik
jakiegoś wyrażenia, ale nie można użyć w nim żadnej funkcji, bo spowoduje to błąd składni.
Przykład #7 Deklaracja zmiennych statycznych
<?php
function foo(){
static $int = 0; // prawidłowo
static $int = 1+2; // prawidłowo (od PHP 5.6)
static $int = sqrt(121); // błąd (ponieważ jest to funkcja)
$int++;
echo $int;
}
?>
Informacja:
Deklaracje statyczne są rozwiązywane w czasie kompilacji.
Referencje do zmiennych statycznych i globalnych
Silnik Zend 1 (ang. Zend Engine 1) napędzający PHP4, implementuje modyfikatory
statyczny oraz
globalny
dla zmiennych, pod względem
referencji. Na przykład, w rzeczywistości globalna zmienna
wprowadzona wewnątrz zasięgu funkcji z wyrażeniem global
na dziś dzień tworzy referencję do zmiennej globalnej. Takie zachowanie może
prowadzić do nieoczekiwanych sytuacji, czego dowodzi poniższy przykład:
Powyższy przykład wyświetli:
NULL
object(stdClass)(0) {
}
Podobna sytuacja dotyczy deklaracji static.
Referencje nie są magazynowane statycznie:
Powyższy przykład wyświetli:
Obiekt statyczny: NULL
Obiekt statyczny: NULL
Obiekt statyczny: NULL
Obiekt statyczny: object(stdClass)(1) {
["property"]=>
int(1)
}
Ten przykład pokazuje, że podczas przypisywania referencji do zmiennej
statycznej, nie następuje zapamiętanie, gdy wywołasz
funkcję &get_instance_ref() po raz drugi.