Глобальные переменные в PHP считаются плохой практикой? Если так, то почему?

function foo () {
    global $var;
    // rest of code
}

в моих небольших PHP-проектах я обычно иду процедурным путем. Обычно у меня есть переменная, содержащая конфигурацию системы, и когда я хочу получить доступ к этой переменной в функции, я делаю global $var;.

это плохая практика?

6 ответов


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

часто (всегда?) вы можете вызывать функции-члены в таких методах, как preg_replace_callback() как это:

preg_replace_callback('!pattern!', array($obj, 'method'), $str);

посмотреть обратные вызовы дополнительные.

дело в том, что объекты были прикреплены к PHP и в некотором роде приводят к некоторой неловкости.

Не беспокойтесь чрезмерно о применении стандартов или конструкций из разных языков к PHP. Еще одна распространенная ловушка-попытка превратить PHP в чистый язык ООП, вставляя объектные модели поверх всего.

Как и все остальное, используйте "глобальные" переменные, процедурные код, определенная структура и ООП, потому что это имеет смысл, решает проблему, уменьшает объем кода, который вам нужно написать, или делает его более доступным и понятным, а не потому, что вы думаете, что должны.


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

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

но если массив глобальный, нужно проверить все места, где вы используете глобальную переменную, и не только это, вы должны выяснить, в каком порядке эти ссылки на глобальную переменную доступны.

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


Я согласен с клитус. я бы добавил две вещи:--1-->

  1. используйте префикс, чтобы сразу определить его как глобальный (например, $g_)
  2. объявите их в одном месте, не разбрызгивайте их по всему коду.

с наилучшими пожеланиями, Дон!--1-->


кто может возразить против опыта, дипломов колледжа и разработки программного обеспечения? Не я. Я бы только сказал, что при разработке объектно-ориентированных одностраничных PHP-приложений мне больше нравится, когда я знаю, что могу построить все это с нуля, не беспокоясь о столкновениях пространств имен. Строительство с нуля-это то, что многие люди не делать. У них есть работа, срок, бонус или репутация, о которой нужно заботиться. Эти типы, как правило, используют так много встроенных кодов с высокими ставками, что они вообще не могут рисковать, используя глобальные переменные.

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

Если это означает использование нескольких переменных (

Как правило, я бы не сказал, что использование глобальных переменных плохая практика. Я бы сказал, что использование глобальных переменных (флагов и тому подобного) вне глобальной области программы-это нарываться на неприятности и (в долгосрочной перспективе) опрометчивым потому что вы можете потерять след их состояния довольно легко. Кроме того, я бы сказал, что чем больше вы узнаете, тем меньше вы будете полагаться на глобальных переменных, потому что вы испытали "радость" отслеживания ошибок, связанных с их использованием. Это само по себе будет стимулировать вас найти другой способ решить ту же проблему. По совпадению, это имеет тенденцию подталкивать людей PHP в направлении обучения использованию пространств имен и классов (статических членов и т. д...).

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

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


As:

global $my_global; 
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']

это плохая практика (например, Wordpress $pagenow)... хммм

рассмотривать этот:

$my-global = 'Transport me between functions';

ошибка PHP но:

$GLOBALS['my-global'] = 'Transport me between functions';

is не ошибка hypens не столкновение С" общими " объявленными пользователем переменными, такими как $pagenow. И использование верхнего регистра указывает на суперглобальный в использовании, легко обнаружить в коде или отслеживать с найти в файлах

Я использую дефисы, если Im ленивый, чтобы построить классы всего для одного решения, например:

$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';

но в случаях более широкого использования я использую один глобальные переменные в массив:

$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';

последнее для меня,хорошая практика на" cola light "цели или использовать, вместо беспорядка с одноэлементными классами каждый раз, чтобы" кэшировать " некоторые данные. Пожалуйста, сделайте комментарий, если я ошибаюсь или пропустил что-то глупое здесь...


перепостил из законченной так документации Beta

мы можем проиллюстрировать эту проблему следующим псевдо-кодом

function foo() {
     global $bob;
     $bob->doSomething();
}

ваш первый вопрос здесь является очевидным

откуда $bob откуда?

вы запутались? Хороший. Вы только что узнали, почему глобалы сбивают с толку и считаются плохой практикой. Если бы это была настоящая программа, ваш следующий бит удовольствия, чтобы пойти отслеживать все примеры $bob и надеюсь, что вы найдете правильный (это еще хуже, если $bob используется везде). Хуже, если кто-то другой идет и определяет $bob (или вы забыли и повторно использовали эту переменную) ваш код может сломаться (в приведенном выше примере кода наличие неправильного объекта или отсутствие объекта вообще вызовет фатальную ошибку). Поскольку практически все PHP-программы используют код типа include('file.php'); ваша работа, сохранив код, как это становится экспоненциально сложнее, чем больше файлов вы добавлять.

как мы можем избежать их?

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

function foo(\Bar $bob) {
    $bob->doSomething();
}

это много легче понять и поддержать. Нет никаких догадок, где $bob был настроен, потому что вызывающий отвечает за знание этого (он передает нам то, что нам нужно знать). Еще лучше, мы можем использовать заявления типа чтобы ограничить то, что передается. Итак, мы знаем, что $bob - это экземпляр Bar класс или экземпляр дочернего элемента Bar, то есть, мы знаем, мы можем использовать методы этого класса. В сочетании со стандартным загрузчиком (доступным с PHP 5.3) теперь мы можем отслеживать, где Bar определяется. PHP 7.0 или более поздней версии включает расширенные объявления типов, где вы также можете использовать скалярные типы (например,int или string).