Что такое «переменная область»?
Переменные имеют ограниченную «область видимости» или «места, из которых они доступны». То, что вы $foo = 'bar';
однажды написали где-то в своем приложении, не означает, что вы можете ссылаться $foo
из любого другого места внутри приложения. Переменная $foo
имеет определенную область, в которой она действительна, и только код в той же области имеет доступ к переменной.
Как определяется область действия в PHP?
Очень просто: PHP имеет область действия функции . Это единственный вид разделителя области видимости, который существует в PHP. Переменные внутри функции доступны только внутри этой функции. Переменные вне функций доступны везде вне функций, но не внутри какой-либо функции. Это означает, что в PHP есть одна специальная область: глобальная область. Любая переменная, объявленная вне какой-либо функции, находится в этой глобальной области видимости.
Пример:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
находится в глобальной области видимости, $baz
находится в локальной области видимости изнутри myFunc
. Только код внутри myFunc
имеет доступ к $baz
. Только код снаружи 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
Область и включенные файлы
Границы файла не разделяют область видимости:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
К include
d-коду применяются те же правила, что и к любому другому коду: только function
отдельная область. Для целей охвата вы можете подумать о включении таких файлов, как копирование и вставка кода:
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
В приведенном выше примере, a.php
был включен внутри myFunc
, любые переменные внутри a.php
имеют только локальную область видимости функции. Просто потому , что они появляются , чтобы быть в глобальном масштабе в a.php
вовсе не обязательно означает , что они, на самом деле зависит от того, какой контекст , что код включен / выполняется в.
Как насчет функций внутри функций и классов?
Каждая новая function
декларация вводит новую область, это так просто.
(анонимные) функции внутри функций
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
классы
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
Для чего нужна сфера?
Решение проблем с областями видимости может показаться раздражающим, но ограниченная область применения переменных необходима для написания сложных приложений! Если бы каждая объявленная вами переменная была бы доступна из любого места внутри вашего приложения, вы бы пошагово перебирали все переменные, не имея реального способа отследить, что и что изменится. Существует только так много разумных имен, которые вы можете дать своим переменным, вы, вероятно, захотите использовать переменную " $name
" более чем в одном месте. Если бы вы могли иметь это уникальное имя переменной только один раз в своем приложении, вам пришлось бы прибегнуть к действительно сложным схемам именования, чтобы убедиться, что ваши переменные уникальны и что вы не меняете неправильную переменную из неправильного фрагмента кода.
Заметим:
function foo() {
echo $bar;
}
Если бы не было области видимости, что бы делала вышеуказанная функция? Откуда $bar
берутся? В каком состоянии он находится? Это даже инициализировано? Вы должны проверять каждый раз? Это не подлежит ремонту. Что приводит нас к ...
Пересечение границ границ
Правильный путь: передача переменных в и из
function foo($bar) {
echo $bar;
return 42;
}
Переменная $bar
явно входит в эту область в качестве аргумента функции. Глядя на эту функцию, становится ясно, откуда берутся значения, с которыми она работает. Затем он явно возвращает значение. Вызывающая сторона уверена, что знает, с какими переменными будет работать функция и откуда возвращаются ее значения:
$baz = 'baz';
$blarg = foo($baz);
Расширение области видимости переменных в анонимные функции
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
Анонимная функция явно включает в себя $foo
из окружающей ее области видимости. Обратите внимание, что это не то же самое, что глобальный область.
Неправильный путь: global
Как было сказано ранее, глобальная область видимости является чем-то особенным, и функции могут явно импортировать переменные из нее:
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
Эта функция использует и изменяет глобальную переменную $foo
. Не делай этого! (Если только вы действительно действительно действительно не знаете, что делаете, и даже тогда: не надо!)
Все, что вызывает эта функция, видит так:
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
Там нет никаких признаков того, что эта функция имеет какие-либо побочные эффекты , но это так. Это очень легко становится запутанным беспорядком, поскольку некоторые функции продолжают изменяться и требуют некоторого глобального состояния. Вы хотите, чтобы функции были без состояния , действовали только на свои входы и возвращали определенный вывод, сколько бы раз вы их ни вызывали.
Вы должны избегать использования глобальной области видимости в максимально возможной степени; Скорее всего, вы не должны «вытягивать» переменные из глобальной области в локальную область.