global в PHP: глобальные переменные и массив $GLOBALS

global в PHP: глобальные переменные и массив $GLOBALS Полезное

Инструкция global в PHP — это способ дать функции доступ к переменной, которая объявлена вне ее, в глобальной области видимости. По умолчанию функция такую переменную не видит: любое имя внутри функции считается локальным. Тот же доступ дает суперглобальный массив $GLOBALS.

Ниже разберу, чем локальная область видимости отличается от глобальной, как связать функцию с внешней переменной через global и через $GLOBALS, чем эти два способа отличаются, что изменилось в $GLOBALS начиная с PHP 8.1 и почему глобальными переменными лучше не злоупотреблять. Примеры даны для PHP 8.x.

Область видимости: локальная и глобальная

Область видимости — это часть программы, где переменная существует и доступна по имени. В PHP их две основные.

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

Глобальная область — код вне функций, на верхнем уровне скрипта. Переменные, объявленные здесь, доступны в остальном коде верхнего уровня.

Ключевая особенность PHP: в отличие от многих языков, функция НЕ видит глобальные переменные автоматически. Внутри функции имя $x — это всегда локальная переменная, даже если снаружи есть глобальная $x с тем же именем. Связи между ними по умолчанию нет.

Покажу это на примере. Имя совпадает, но переменные разные:

<?php
$x = 555;

function test() {
    $x = 888;       // это локальная переменная функции
    echo $x, "\n";
}

test();             // печатает локальную 888
echo $x, "\n";      // печатает глобальную 555

Вывод:

888
555

Сначала вызывается test() и печатает свою локальную $x (888). Затем echo на верхнем уровне печатает глобальную $x (555). Присваивание внутри функции не тронуло внешнюю переменную — это две независимые ячейки с одинаковым именем.

Проблема: функция не меняет внешнюю переменную

Из-за такого разделения наивная попытка изменить глобальную переменную из функции не работает. Функция создает свою локальную копию имени и правит ее.

Неверный код (расчет на то, что функция увидит внешний $total):

<?php
$total = 100;

function addBonus() {
    $total = $total + 50;   // справа - локальная неинициализированная переменная
    echo $total, "\n";
}

addBonus();
echo $total, "\n";

Фактический вывод в PHP 8.x:

PHP Warning:  Undefined variable $total in ... on line 5
50
100

Что произошло: внутри функции $total в правой части — это новая локальная переменная, которой еще не присвоили значение. PHP 8 выдает предупреждение Undefined variable и подставляет null, а null в арифметике равен 0. Поэтому локальная $total стала 0 + 50 = 50, а глобальная так и осталась 100. Именно для этого случая и нужна инструкция global.

Инструкция global

global внутри функции объявляет, что перечисленные имена ссылаются на глобальные переменные, а не на локальные. После этого функция читает и меняет именно внешние значения.

Исправим предыдущий пример:

<?php
$total = 100;

function addBonus() {
    global $total;          // связываем имя с глобальной переменной
    $total = $total + 50;
    echo $total, "\n";
}

addBonus();                 // 150
echo $total, "\n";          // 150

Вывод:

150
150

Теперь обе строки печатают 150: функция изменила ту же переменную, что видна снаружи. Через запятую можно объявить сразу несколько имен — global $x, $y; — ограничений на их число нет.

Классический пример со сложением двух глобальных переменных:

<?php
$x = 5;
$y = 10;

function sum() {
    global $x, $y;
    $y = $x + $y;
}

sum();
echo $y, "\n";   // 15

Вывод:

15

Важно понимать механику: global $x; не копирует значение, а создает в функции ссылку на глобальную переменную. Строка эквивалентна записи $x = &$GLOBALS['x'];. Поэтому запись в такую переменную меняет глобальную, а unset($x) внутри функции разорвет только локальную ссылку — сама глобальная переменная сохранится.

Массив $GLOBALS

Второй способ добраться до глобальной области — суперглобальный массив $GLOBALS. Это ассоциативный массив, где ключ — имя глобальной переменной (без знака $), а значение — ее содержимое. Тот же пример через $GLOBALS:

<?php
$x = 5;
$y = 10;

function sum() {
    $GLOBALS['y'] = $GLOBALS['x'] + $GLOBALS['y'];
}

sum();
echo $y, "\n";   // 15

Вывод:

15

Результат тот же — 15, но объявлять global не понадобилось. Слово суперглобальный означает, что массив доступен в любой области видимости автоматически: и на верхнем уровне, и внутри любой функции, без предварительного объявления. К этому же семейству относятся $_GET, $_POST, $_SESSION, $_SERVER и другие — их тоже не нужно объявлять через global.

Одно уточнение по версиям. Начиная с PHP 8.1 массив $GLOBALS стал доступен только для чтения как единое целое: нельзя перезаписать его целиком ($GLOBALS = [...]) или передать по ссылке. Но запись в отдельный элемент — $GLOBALS['y'] = ... — по-прежнему работает и меняет глобальную переменную, как в примере выше. Так что на код доступа к конкретным переменным это изменение не влияет.

global или $GLOBALS: что выбрать

Оба способа решают одну задачу, отличия — в деталях.

Признак Инструкция global Массив $GLOBALS
Как обращаться по обычному имени $x после global $x; по ключу $GLOBALS['x']
Нужно объявлять да, в начале функции нет, доступен сразу
Что создает ссылку на глобальную переменную прямой доступ к элементу массива
Имя ключа динамически нет, имя фиксировано в коде да, ключом может быть переменная $GLOBALS[$name]
Видно в любой области только внутри функции после объявления в любой области, суперглобален

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

Почему глобальными переменными лучше не злоупотреблять

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

Более предсказуемая альтернатива — передавать данные явно, через аргументы и возвращаемое значение:

<?php
function addBonus(int $total, int $bonus): int
{
    return $total + $bonus;   // ничего снаружи не меняем
}

$total = 100;
$total = addBonus($total, 50);
echo $total, "\n";   // 150

Вывод:

150

Здесь функция не зависит от глобального состояния: что получает и что отдает — видно по сигнатуре. Для констант приложения используют const или define(), а для общего состояния в больших проектах — объекты и внедрение зависимостей. global и $GLOBALS остаются удобными в коротких скриптах и при работе со старым кодом, но в новом коде их стоит применять осознанно, а не по привычке.

Выводы

  • По умолчанию функция в PHP не видит глобальные переменные: любое имя внутри нее локально.
  • Инструкция global $x; связывает локальное имя с глобальной переменной; фактически это ссылка, эквивалент $x = &$GLOBALS['x'];.
  • Суперглобальный массив $GLOBALS['x'] дает тот же доступ без объявления и работает в любой области видимости.
  • С PHP 8.1 нельзя перезаписать $GLOBALS целиком, но запись в отдельные элементы работает по-прежнему.
  • Глобальные переменные связывают код неявными зависимостями; где можно, данные лучше передавать через аргументы и возвращаемые значения.

Где применяется и что учить дальше

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

Освойте тему на практике

Если хочется освоить PHP системно — от областей видимости и ООП до архитектуры реальных приложений, — посмотрите курс Разработчик PHP. Оценить формат и уровень до старта помогают бесплатные открытые уроки Otus — живые занятия с преподавателями.

FAQ

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

Что делает global на верхнем уровне скрипта, вне функции? Практически ничего полезного: в глобальной области переменная и так глобальна, объявлять ее через global не нужно. Инструкция имеет смысл только внутри функций и методов.

Нужно ли объявлять global для $_POST, $_GET и других суперглобальных массивов? Нет. Суперглобальные массивы ($_POST, $_GET, $_SERVER, $_SESSION и прочие) доступны в любой области видимости сами по себе, global для них не требуется.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)