Intereting Posts
веб-страниц с большим количеством вызовов AJAX Как объединить массив с ключом и значением без foreach в PHP Безопасный метод шифрования LAMP Получите последние значения в GROUP BY, используя Laravel Rloquent ORM массив json для массива событий в jQuery fullcalendar PHP, загружающий несколько изображений и вставляя в базу данных Любое альтернативное решение для получения этой работы? Php-код работает неправильно, но работает код mysql PHP Получение XPath DOMNode Larvel 4.2 artisan CLI больше не работает после обновления композитора Как использовать разбиение на страницы вместе с методом laravel eloquent find in laravel 5.4 Архивы даты для пользовательских типов сообщений Самый чистый способ читать настройки конфигурации из файла PHP и загружать весь код проекта с помощью сценария оболочки передать массив с файлом списка в цикл curl Рекомендуемая замена устаревшего метода call_user_method? Как защитить страницу только для зарегистрированных пользователей?

Ссылка: что такое переменная область, какие переменные доступны из того, где и какие ошибки «неопределенной переменной»?

Примечание. Это справочный вопрос для рассмотрения области переменных в PHP. Пожалуйста, закройте любой из многих вопросов, соответствующих этому шаблону, как дубликат этого.

Что такое «переменная область» в PHP? Доступны ли переменные из одного .php-файла в другом? Почему у меня иногда возникают ошибки «неопределенной переменной» ?

Что такое «переменная область»?

Переменные имеют ограниченный «объем» или «места, из которых они доступны». Просто потому, что вы написали $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, применимого к любому другому коду: только для отдельной области. Для целей охвата вы можете подумать о включении таких файлов, как копирование и вставка кода:

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?!?!! с baz(); // outputs "bar" unset($foo); baz(); // no output, WTF?! baz(); // outputs "baz", WTF?!?!! 

Нет никаких признаков того, что эта функция имеет какие-либо побочные эффекты , но это так. Это очень легко становится запутанным беспорядком, поскольку некоторые функции продолжают изменяться и требуют некоторого глобального состояния. Вы хотите, чтобы функции были неактивными , действовали только на своих входах и возвращали определенный результат, однако много раз вы их называете.

Вы должны как можно больше избегать использования глобального масштаба; вы, конечно, не должны «вытягивать» переменные из глобальной области в локальную область.

Объем переменной – это контекст, в котором он определен. По большей части все переменные PHP имеют только одну область. В эту единую область охвата включены и требуемые файлы. Например:

 <?php $a = 1; include 'b.inc'; ?> 

Здесь переменная $a будет доступна в включенном сценарии b.inc . Однако в пользовательских функциях вводится локальная функция. Любая переменная, используемая внутри функции, по умолчанию ограничена областью локальных функций. Например:

 <?php $a = 1; /* global scope */ function test() { echo $a; /* reference to local scope variable */ } test(); ?> 

Этот скрипт не будет выдавать какой-либо вывод, потому что оператор echo ссылается на локальную версию переменной $ a, и ей не присвоено значение в этой области. Вы можете заметить, что это немного отличается от языка C в том, что глобальные переменные в C автоматически доступны для функций, если они не переопределены локальным определением. Это может вызвать некоторые проблемы в том, что люди могут непреднамеренно изменить глобальную переменную. В PHP глобальные переменные должны быть объявлены глобальными внутри функции, если они будут использоваться в этой функции.

Хотя переменные, определенные внутри области действия, не могут быть доступны извне, это не означает, что вы не можете использовать их значения после завершения этой функции. PHP имеет известное static ключевое слово, которое широко используется в объектно-ориентированном PHP для определения статических методов и свойств, но следует иметь в виду, что static также могут использоваться внутри функций для определения статических переменных.

Что это за «статическая переменная»?

Статическая переменная отличается от обычной переменной, определенной в области функции, в случае, если она не потеряет значение, когда выполнение программы выходит из этой области. Рассмотрим следующий пример использования статических переменных:

 function countSheep($num) { static $counter = 0; $counter += $num; echo "$counter sheep jumped over fence"; } countSheep(1); countSheep(2); countSheep(3); 

Результат:

 1 sheep jumped over fence 3 sheep jumped over fence 6 sheep jumped over fence 

Если бы мы определили $counter без static то каждый раз эхо-значение будет таким же, как параметр $num переданный функции. Использование static позволяет построить этот простой счетчик без дополнительного обхода.

Варианты использования статических переменных

  1. Сохранение значений между последовательными вызовами функции.
  2. Сохранять значения между рекурсивными вызовами, когда нет пути (или нет цели) для передачи их в качестве параметров.
  3. Кэш-значение, которое обычно лучше извлекать один раз. Например, результат чтения неизменяемого файла на сервере.

Трюки

Статическая переменная существует только в области локальных функций. Он не может быть доступен за пределами функции, в которой он был определен. Таким образом, вы можете быть уверены, что он сохранит свое значение без изменений до следующего вызова этой функции.

Статическая переменная может быть определена только как скаляр или как скалярное выражение (начиная с PHP 5.6). Присвоение других ценностей неизбежно приводит к отказу, по крайней мере, на момент написания этой статьи. Тем не менее вы можете сделать это только на следующей строке вашего кода:

 function countSheep($num) { static $counter = 0; $counter += sqrt($num);//imagine we need to take root of our sheep each time echo "$counter sheep jumped over fence"; } 

Результат:

 2 sheep jumped over fence 5 sheep jumped over fence 9 sheep jumped over fence 

Статическая функция «делится» между методами объектов того же класса. Это легко понять, просмотрев следующий пример:

 class SomeClass { public function foo() { static $x = 0; echo ++$x; } } $object1 = new SomeClass; $object2 = new SomeClass; $object1->foo(); // 1 $object2->foo(); // 2 oops, $object2 uses the same static $x as $object1 $object1->foo(); // 3 now $object1 increments $x $object2->foo(); // 4 and now his twin brother 

Это работает только с объектами того же класса. Если объекты из разных классов (даже расширяя друг друга), поведение статических варов будет таким, как ожидалось.

Является ли статическая переменная единственным способом сохранить значения между вызовами функции?

Другим способом сохранения значений между вызовами функций является использование замыканий. Закрытие было введено в PHP 5.3. В двух словах они позволяют ограничить доступ к некоторому набору переменных внутри области функций другой анонимной функцией, которая будет единственным способом доступа к ним. Быть в закрывающих переменных могут имитировать (более или менее успешно) концепции ООП, такие как «константы класса» (если они были переданы в закрытии по значению) или «частные свойства» (если они переданы по ссылке) в структурированном программировании.

Последний фактически позволяет использовать замыкания вместо статических переменных. Что нужно использовать, разработчик всегда должен решить, но следует упомянуть, что статические переменные определенно полезны при работе с рекурсиями и заслуживают того, чтобы их заметили разработчики.