PHP: global внутри функции не показывает переменную

190
31 января 2018, 15:17

Опишу ситуацию.

В теле метода класса подключается файл ($dataFile):

public function method()
{
    $data = include_once $dataFile;
    $content = $this->renderFile($template, $data);
}

В подключаемом файле следующая логика:

$lang = dolang();
// code...
while ($country = $stmt->fetch(PDO::FETCH_ASSOC)) {
    // code...
    $countries[] = [
       // code...
       'name'        => $name,
       'title'       => getCountryTitle($name)
    ];
}
return compact('countries');
function getCountryTitle(string $name) {
    global $lang;
    return str_replace('%COUNTRY%', sklon($name), $lang['catalog_meta_title_country']);
}

Этот подключаемый файл последовательно выполняет код используя некоторые функции объявленные в нём же и в конце возвращает некий результат.

И вот проблема в том, что внутри функции getCountryTitle глобальная переменная $lang не видна, она null соответственно. Аналогично с другими переменными и другими функциями.

Смотрю под отладчиком - при выполнении логики в файле не заходя в функцию глобальные переменные инициализированы и всё хорошо. При заходе в функцию и объявляя их глобальными - они невидимы.

В чём может быть проблема?

Answer 1

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

Наиболее правильный подход заключался бы в том, чтобы поместить набор операций в виде функций/класса с собственным именем в файл, подключить файл (без какого-либо оператора возврата за пределами функций), а затем вызывать функцию явно с требуемым набором аргументов.

Так в чем проблема-то?

Все предельно просто, вы делаете include внутри метода method, а значит переменные указанные в подключаемом файле инициализируются в области видимости метода method. Следовательно, переменная $lang не является глобальной, а ограничена видимостью метода, а вы обращаетесь к глобальной переменной, поэтому при использовании модификатора global она будет равна null.

Если делать include в глобальной области видимости, тогда переменная lang станет общедоступной (global) и ее использование станет возможным. Это легко проверить, достаточно в подключаемом файле перед началом определения какой-либо переменной написать global $переменная.

Пример:

include 'file1.php';
function include2() {
  include 'file2.php';
}
  • file1.php определен в глобальной области видимости.
  • file2.php определен в локальной области видимости функции include2.

Подход с глобальными переменными и таким include - это костыль, который принесет вам проблем в будущем. Функции должны быть определены явно, иметь уникальное имя и выполняться по требованию.

А почему подход с глобальными переменными плохой?

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

Предположим, у вас есть функция, результат которой зависит от глобальной переменной. Вы вызываете её, вызываете - но через 10 минут функция начинает возвращать неверные результаты. Что случилось? Ведь на вход вы передаёте ей всё тот же набор параметров? Гм, кто-то поменял значение глобальной переменной... Кто это мог быть? Да кто угодно - ведь глобальная переменная доступна всем..

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

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

Знаете какой наилучший префикс для глобальных переменных?

Ответ: //

READ ALSO
Сравнение 2 csv файлов

Сравнение 2 csv файлов

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

218
Парсить ссылку при переходе на сайт

Парсить ссылку при переходе на сайт

решил сделать партнерку, вот такого вида ссылка https://mysitecom/p644320/vip , где p644320 - это id того, кто привлекает, как мне при переходе на мой сайт обрабатывать...

153
запрос POST с сервера Node.js для PHP

запрос POST с сервера Node.js для PHP

Товарищи, скажите что делаю не так?

181
WooCommerce+WP Job Manager в My Account не работает pagination

WooCommerce+WP Job Manager в My Account не работает pagination

Есть 2 известных плагина: WooCommerce, WP Job ManagerПри отображении списка вакансий или резюме в админке пользователя (Используется админка Woo) не работает...

198