Co to jest „zakres zmienny”?
Zmienne mają ograniczony „zakres” lub „miejsca, z których są dostępne”. To, że napisałeś $foo = 'bar';
kiedyś gdzieś w aplikacji, nie oznacza, że możesz odwoływać się $foo
z dowolnego miejsca w aplikacji. Zmienna $foo
ma określony zakres, w którym jest prawidłowa i tylko kod z tego samego zakresu ma dostęp do zmiennej.
Jak zdefiniowany jest zakres w PHP?
Bardzo proste: PHP ma zakres funkcji . To jedyny rodzaj separatora zakresu, który istnieje w PHP. Zmienne wewnątrz funkcji są dostępne tylko wewnątrz tej funkcji. Zmienne poza funkcjami są dostępne gdziekolwiek poza funkcjami, ale nie wewnątrz żadnej funkcji. Oznacza to, że w PHP jest jeden specjalny zakres: globalny zasięg . Każda zmienna zadeklarowana poza jakąkolwiek funkcją mieści się w tym zasięgu globalnym.
Przykład:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
jest w zasięgu globalnym , $baz
w zasięgu lokalnymmyFunc
. Tylko kod wewnątrz myFunc
ma dostęp $baz
. Dostęp ma tylko kod z zewnątrz . Żaden nie ma dostępu do drugiego:myFunc
$foo
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
echo $foo; // doesn't work
echo $baz; // works
}
echo $foo; // works
echo $baz; // doesn't work
Zakres i dołączone pliki
Granice plików nie oddzielają zakresu:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
Te same zasady mają zastosowanie do include
kodu d, co do każdego innego kodu: tylko function
oddzielny zakres. Ze względu na zakres możesz pomyśleć o dołączeniu plików, takich jak kopiowanie i wklejanie kodu:
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
W powyższym przykładzie, a.php
został zawarty w środku myFunc
, wszystkie zmienne wewnątrz a.php
mają tylko lokalny zasięg funkcji. To, że wydają się być w zasięgu globalnym, a.php
niekoniecznie oznacza, że tak jest, w rzeczywistości zależy to od kontekstu, w którym kod jest zawarty / wykonywany.
A co z funkcjami wewnątrz funkcji i klas?
Każda nowa function
deklaracja wprowadza nowy zakres, to takie proste.
(anonimowe) funkcje wewnątrz funkcji
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
zajęcia
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
Do czego służy luneta?
Radzenie sobie z problemami z zakresem może wydawać się irytujące, ale ograniczony zakres zmiennych jest niezbędny do pisania złożonych aplikacji! Gdyby każda zadeklarowana zmienna była dostępna z dowolnego miejsca w aplikacji, przechodziłbyś przez wszystkie zmienne bez rzeczywistego sposobu na śledzenie, co się zmienia. Jest tylko tyle sensownych nazw, które możesz nadać swoim zmiennym, prawdopodobnie będziesz chciał użyć zmiennej " $name
" w więcej niż jednym miejscu. Gdybyś mógł mieć tę unikalną nazwę zmiennej tylko raz w swojej aplikacji, musiałbyś uciekać się do naprawdę skomplikowanych schematów nazewnictwa, aby upewnić się, że zmienne są unikalne i że nie zmieniasz niewłaściwej zmiennej z niewłaściwego fragmentu kodu.
Przestrzegać:
function foo() {
echo $bar;
}
Gdyby nie było zakresu, co zrobiłaby powyższa funkcja? Skąd się $bar
bierze? Jaki ma stan? Czy jest w ogóle zainicjowany? Czy za każdym razem musisz sprawdzać? Tego nie da się utrzymać. Co prowadzi nas do ...
Przekraczanie granic zakresu
Właściwy sposób: przekazywanie i wychodzenie zmiennych
function foo($bar) {
echo $bar;
return 42;
}
Zmienna $bar
jawnie wchodzi do tego zakresu jako argument funkcji. Wystarczy spojrzeć na tę funkcję, aby było jasne, skąd pochodzą wartości, z którymi ona pracuje. Następnie jawnie zwraca wartość. Wzywający ma pewność, że wie, z jakimi zmiennymi funkcja będzie współpracować i skąd pochodzą jej wartości zwracane:
$baz = 'baz';
$blarg = foo($baz);
Rozszerzenie zakresu zmiennych na funkcje anonimowe
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
Funkcja anonimowa jawnie obejmuje $foo
z otaczającego zakresu. Zauważ, że to nie to samo, co zasięg globalny .
Zły kierunek: global
Jak wspomniano wcześniej, zasięg globalny jest nieco wyjątkowy, a funkcje mogą jawnie importować z niego zmienne:
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
Ta funkcja używa i modyfikuje zmienną globalną $foo
. Nie rób tego! (Chyba że naprawdę naprawdę naprawdę wiesz, co robisz, a nawet wtedy: nie rób tego!)
Wszystko, co widzi wywołujący tę funkcję, to:
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
Nic nie wskazuje na to, że ta funkcja ma jakiekolwiek skutki uboczne , ale tak jest. Bardzo łatwo staje się to zagmatwanym bałaganem, ponieważ niektóre funkcje ciągle się modyfikują i wymagają pewnego stanu globalnego. Chcesz, aby funkcje były bezstanowe , działały tylko na swoich wejściach i zwracały zdefiniowane dane wyjściowe, niezależnie od tego, ile razy je wywołasz.
W miarę możliwości należy unikać używania zakresu globalnego; z całą pewnością nie powinieneś „wyciągać” zmiennych z zasięgu globalnego do zasięgu lokalnego.