Перейти к основному содержимому

Глобальные переменные и суперглобальные массивы в PHP

Разработчику Архитектору

Глобальные переменные и суперглобальные массивы в PHP

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

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


Что такое глобальные переменные в PHP

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

В PHP по умолчанию переменные, созданные в основном теле скрипта, имеют глобальную область видимости. Однако внутри функций они недоступны, пока не будет использован ключевое слово global или обращение через массив $GLOBALS.

Пример:

$color = "зелёный";

function showColor() {
global $color;
echo $color; // выведет "зелёный"
}

showColor();

Альтернативный способ — использование $GLOBALS:

$color = "синий";

function showColorAlt() {
echo $GLOBALS['color']; // выведет "синий"
}

showColorAlt();

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


Что такое суперглобальные массивы

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

PHP определяет следующие суперглобальные массивы:

  • $_SERVER
  • $_GET
  • $_POST
  • $_FILES
  • $_COOKIE
  • $_SESSION
  • $_REQUEST
  • $_ENV
  • $GLOBALS

Кроме того, при запуске скрипта из командной строки доступны специальные переменные:

  • $argc
  • $argv

Рассмотрим каждый из них подробно.


$_SERVER — информация о сервере и запросе

Массив $_SERVER содержит данные, предоставленные веб-сервером и относящиеся к текущему HTTP-запросу или среде выполнения скрипта.

Основные элементы $_SERVER:

  • $_SERVER['HTTP_HOST'] — доменное имя или IP-адрес хоста, к которому обратился клиент.
  • $_SERVER['REQUEST_METHOD'] — метод HTTP-запроса (GET, POST, PUT, DELETE и т.д.).
  • $_SERVER['REQUEST_URI'] — URI запрошенного ресурса (без домена).
  • $_SERVER['QUERY_STRING'] — строка запроса после знака ?.
  • $_SERVER['SCRIPT_NAME'] — путь к исполняемому PHP-файлу относительно корня сайта.
  • $_SERVER['REMOTE_ADDR'] — IP-адрес клиента.
  • $_SERVER['HTTP_USER_AGENT'] — строка, идентифицирующая браузер или клиентское приложение.
  • $_SERVER['HTTPS'] — присутствует и имеет значение 'on', если соединение защищено через HTTPS.
  • $_SERVER['DOCUMENT_ROOT'] — абсолютный путь к корневой директории сайта на сервере.
  • $_SERVER['SERVER_SOFTWARE'] — название и версия веб-сервера (например, Apache/2.4.41).

Пример использования:

echo "Вы используете браузер: " . $_SERVER['HTTP_USER_AGENT'];
echo "Ваш IP: " . $_SERVER['REMOTE_ADDR'];
if (!empty($_SERVER['HTTPS'])) {
echo "Соединение защищено.";
}

⚠️ Предупреждение
Данные из $_SERVER могут быть подделаны клиентом (особенно заголовки, начинающиеся с HTTP_). Их нельзя использовать без валидации в критически важных операциях, таких как авторизация или логика безопасности.


$_GET — данные из URL-строки

Массив $_GET содержит параметры, переданные в URL после знака вопроса (?) в виде пар ключ=значение, разделённых символом &.

Пример URL:
https://example.com/page.php?name=Иван&age=30

В этом случае:

echo $_GET['name']; // "Иван"
echo $_GET['age']; // "30"

Особенности:

  • Все значения в $_GET являются строками.
  • Если параметр не задан, обращение к нему вызовет ошибку уровня Notice. Рекомендуется проверять существование ключа через isset() или array_key_exists().
  • Для защиты от XSS и других атак необходимо экранировать вывод через htmlspecialchars().

Безопасное чтение:

$name = isset($_GET['name']) ? htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8') : 'Гость';
echo "Привет, $name!";

$_POST — данные из тела HTTP-запроса

Массив $_POST содержит данные, отправленные клиентом методом POST, обычно через HTML-формы с атрибутом method="post".

Пример формы:

<form method="post" action="process.php">
<input type="text" name="email">
<input type="submit">
</form>

В process.php:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
// Валидация и обработка
}

Особенности:

  • Как и $_GET, все значения — строки.
  • Не отображаются в адресной строке, что делает POST более подходящим для передачи конфиденциальных данных (хотя это не замена шифрованию!).
  • Максимальный размер данных ограничен настройками сервера (post_max_size в php.ini).

$_FILES — загруженные файлы

При отправке формы с атрибутом enctype="multipart/form-data" и полем <input type="file">, данные о загруженных файлах попадают в массив $_FILES.

Структура $_FILES['имя_поля']:

  • name — оригинальное имя файла на клиенте.
  • type — MIME-тип (может быть подделан!).
  • size — размер в байтах.
  • tmp_name — временный путь на сервере, куда файл загружен.
  • error — код ошибки (0 = успешно).

Пример обработки:

if ($_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
$tmpName = $_FILES['avatar']['tmp_name'];
$target = __DIR__ . '/uploads/' . basename($_FILES['avatar']['name']);
if (move_uploaded_file($tmpName, $target)) {
echo "Файл загружен.";
}
}

⛔ Осторожно
Никогда не доверяйте $_FILES['name'] напрямую. Всегда генерируйте безопасное имя файла и проверяйте тип по содержимому (например, через finfo_file), а не по расширению.


Массив $_COOKIE содержит cookies, отправленные браузером вместе с запросом. Cookies — это небольшие фрагменты данных, сохранённые на стороне клиента и автоматически передаваемые при каждом запросе к домену.

Устанавливаются через функцию setcookie():

setcookie('user_id', '123', time() + 3600, '/', '', true, true);

После этого в последующих запросах:

echo $_COOKIE['user_id'] ?? 'не установлен';

Безопасность:

  • Используйте флаги HttpOnly и Secure.
  • Не храните в cookie чувствительные данные (пароли, токены без шифрования).
  • Всегда проверяйте целостность и подлинность данных.

$_SESSION — данные сессии

Сессия — механизм хранения данных на сервере, связанных с конкретным пользователем. Идентификатор сессии обычно передаётся через cookie (PHPSESSID) или URL.

Перед использованием сессии необходимо вызвать session_start():

session_start();
$_SESSION['user_id'] = 456;

В последующих запросах:

session_start();
echo $_SESSION['user_id'] ?? 'не авторизован';

Особенности:

  • Данные хранятся на сервере (в файлах, Redis, базе и т.д.), что делает их безопаснее cookies.
  • Сессии завершаются при закрытии браузера (если не настроено иное) или по таймауту.
  • Уязвимы к атакам hijacking и fixation — требуют защиты через регенерацию ID и HTTPS.

$_REQUEST — объединённый массив входных данных

Массив $_REQUEST содержит данные из $_GET, $_POST и $_COOKIE (в зависимости от настройки request_order или variables_order в php.ini).

По умолчанию порядок: GP (сначала GET, потом POST), но может включать и C (cookies).

Проблемы:

  • Неопределённость источника данных.
  • Повышает риск коллизий имён (например, ?id=1 и форма с id=2).
  • Считается устаревшим и небезопасным подходом.

📌 Внимание
Использование $_REQUEST не рекомендуется. Всегда явно указывайте источник: $_GET, $_POST или $_COOKIE.


$_ENV — переменные окружения

Массив $_ENV содержит переменные среды, установленные в операционной системе или веб-сервере.

Примеры:

  • $_ENV['HOME'] — домашняя директория пользователя (в CLI).
  • $_ENV['DATABASE_URL'] — строка подключения к БД (часто используется в продакшене).

Однако поведение зависит от настройки variables_order. Во многих конфигурациях $_ENV остаётся пустым, и для получения переменных окружения следует использовать функцию getenv() или $_SERVER.

Рекомендация:

Для надёжного чтения переменных окружения используйте:

$databaseUrl = getenv('DATABASE_URL') ?: $_ENV['DATABASE_URL'] ?? null;

Или, лучше, библиотеки вроде vlucas/phpdotenv для управления .env-файлами.


$GLOBALS — доступ ко всем глобальным переменным

Массив $GLOBALS содержит ссылки на все глобальные переменные, существующие в скрипте. Ключи — имена переменных, значения — их содержимое.

Пример:

$counter = 100;

function increment() {
$GLOBALS['counter']++;
}

increment();
echo $counter; // 101

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


$argc и $argv — аргументы командной строки

При запуске PHP-скрипта из терминала (CLI-режим), переменные $argc и $argv предоставляют доступ к аргументам командной строки.

  • $argc — количество аргументов (включая имя скрипта).
  • $argv — массив аргументов, где $argv[0] — путь к скрипту.

Пример вызова:
php script.php --mode=dev --verbose

Внутри script.php:

echo "Аргументов: " . $argc . "\n";
print_r($argv);
// Выведет:
// Array
// (
// [0] => /path/to/script.php
// [1] => --mode=dev
// [2] => --verbose
// )

Для удобной обработки аргументов рекомендуется использовать библиотеки, такие как symfony/console.


Правила и особенности работы с суперглобальными массивами

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

Автоматическая доступность

Все суперглобальные массивы автоматически существуют в любом контексте выполнения — глобальном, локальном, внутри класса или пространства имён. Их не нужно объявлять с помощью global или передавать как аргументы.

Нельзя использовать как переменные функции

Суперглобальные массивы нельзя передавать по ссылке в качестве параметров функций в старых версиях PHP (до 5.4), а также нельзя использовать в конструкциях вроде foreach ($GLOBALS as &$value), так как это вызывает фатальную ошибку. Это связано с тем, что $GLOBALS является псевдонимом для всех глобальных переменных, и изменение его содержимого может привести к непредсказуемому поведению.

Неизменяемость структуры (в некоторых случаях)

Хотя значения внутри суперглобальных массивов можно изменять, их нельзя полностью перезаписать новым массивом без последствий. Например, присвоение $_POST = [] технически возможно, но нарушает ожидаемое поведение скрипта и затрудняет отладку.

Безопасность и фильтрация

PHP предоставляет расширение filter, которое позволяет безопасно работать с данными из суперглобальных массивов:

$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);

Этот подход предпочтительнее прямого обращения к $_GET['id'], так как он включает встроенную валидацию и санитизацию.


Рекомендации по использованию

Избегайте прямого использования $_REQUEST

Массив $_REQUEST объединяет данные из нескольких источников, что затрудняет определение происхождения данных и увеличивает риск коллизий. Всегда явно указывайте источник: $_GET, $_POST или $_COOKIE.

Валидируйте и саниитизируйте все входные данные

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

  • Проверку типа (is_int(), filter_var()).
  • Ограничение длины.
  • Экранирование при выводе (htmlspecialchars()).
  • Валидацию формата (регулярные выражения, специализированные функции).

Cookies передаются с каждым запросом и могут быть перехвачены. Для хранения идентификаторов сессии используйте $_SESSION, а в cookie — только зашифрованный или хэшированный токен, не раскрывающий внутреннюю структуру приложения.

Используйте session_regenerate_id() после авторизации

Это предотвращает атаки фиксации сессии (session fixation). После успешного входа пользователя вызывайте:

session_start();
// ... проверка логина и пароля ...
$_SESSION['user_id'] = $userId;
session_regenerate_id(true); // true — удаляет старую сессию

Ограничьте использование $argc и $argv в веб-приложениях

Эти переменные актуальны только при запуске скрипта из командной строки. В веб-контексте они недоступны или пусты. Используйте их только в CLI-скриптах (например, cron-задачах, консольных утилитах).


Совместимость и изменения в разных версиях PHP

  • До PHP 5.0.0 суперглобальные массивы не были доступны внутри функций без объявления через global.
  • Начиная с PHP 5.0.0 все суперглобальные массивы стали действительно «суперглобальными».
  • В PHP 7.1 добавлена поддержка типизированных свойств, но это не влияет на суперглобальные массивы, так как они всегда остаются массивами.
  • В PHP 8.0+ улучшена обработка ошибок при работе с файлами, но структура $_FILES осталась неизменной.

Альтернативы и современные подходы

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

  • HTTP-фреймворки (Symfony HttpFoundation, Laravel Request), которые инкапсулируют запрос и предоставляют объектно-ориентированный интерфейс:

    $request->query->get('id');      // вместо $_GET['id']
    $request->request->get('email'); // вместо $_POST['email']
    $request->cookies->get('theme'); // вместо $_COOKIE['theme']
  • PSR-7 — стандартный интерфейс для HTTP-сообщений, который абстрагирует работу с запросами и ответами.

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

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


Освоение главы0%