Суперглобальные переменные

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

$_SERVER

OxPHP формирует $_SERVER из входящего HTTP-запроса в соответствии со спецификацией CGI/1.1. Сначала импортируются переменные окружения процесса, затем задаются CGI-переменные, поэтому значения, специфичные для запроса, всегда переопределяют совпадающие по имени ключи окружения.

Стандартные переменные

Переменная Описание Пример
SCRIPT_FILENAME Абсолютный путь в файловой системе к исполняемому PHP-скрипту /var/www/html/public/index.php
DOCUMENT_ROOT Корневой веб-каталог, задаваемый переменной окружения DOCUMENT_ROOT /var/www/html/public
SERVER_SOFTWARE Идентификатор сервера (содержит версию запущенного OxPHP) OxPHP/0.10.0
SERVER_PROTOCOL Согласованная версия протокола HTTP HTTP/2
REQUEST_METHOD HTTP-метод GET
REQUEST_URI Полный URI со строкой запроса /app?page=2
SCRIPT_NAME Путь исполняемого скрипта относительно DOCUMENT_ROOT — фронт-контроллер в режиме Framework, а не URI запроса /index.php
DOCUMENT_URI Псевдоним SCRIPT_NAME, для совместимости с nginx/PHP-FPM /index.php
PHP_SELF SCRIPT_NAME плюс PATH_INFO, если он присутствует, иначе равен SCRIPT_NAME /index.php/user/42
QUERY_STRING Часть URI, содержащая строку запроса (пустая строка при отсутствии) page=2
SERVER_NAME Имя хоста из заголовка Host example.com
SERVER_PORT Порт из заголовка Host 8080
REMOTE_ADDR IP-адрес клиента 172.17.0.1
REMOTE_PORT Номер порта клиента 54321
HTTPS Устанавливается в "on", когда соединение использует TLS; иначе отсутствует on
REQUEST_SCHEME "https" для TLS-соединений, иначе "http" https
CONTENT_TYPE Значение заголовка Content-Type (без префикса HTTP_) application/json
CONTENT_LENGTH Значение заголовка Content-Length (без префикса HTTP_) 128
REQUEST_TIME Unix-время (целое число) начала запроса 1738800000
REQUEST_TIME_FLOAT Unix-время с точностью до микросекунд 1738800000.123456
GATEWAY_INTERFACE Строка версии CGI CGI/1.1

Если заголовок Host отсутствует, SERVER_NAME по умолчанию принимает значение localhost, а SERVER_PORT80 (или 443 для TLS).

Заголовки HTTP-запроса

Все заголовки HTTP-запроса добавляются в $_SERVER с префиксом HTTP_. Имена заголовков приводятся к верхнему регистру, а дефисы заменяются подчёркиваниями — по соглашениям CGI/1.1:

text
Accept: text/html -> HTTP_ACCEPT X-Forwarded-For: 1.2.3.4 -> HTTP_X_FORWARDED_FOR Authorization: Bearer abc -> HTTP_AUTHORIZATION Cookie: session=xyz -> HTTP_COOKIE
Note

Content-Type и Content-Length появляются без префикса HTTP_ — как CONTENT_TYPE и CONTENT_LENGTH — как того требует спецификация CGI.

За обратным прокси

Когда настроен TRUSTED_PROXIES и узел, от которого поступил запрос, входит в доверенный набор, OxPHP перезаписывает следующие ключи $_SERVER из проброшенных заголовков (X-Forwarded-* или RFC 7239 Forwarded):

Переменная Значение, когда узел доверенный Значение в остальных случаях
REMOTE_ADDR Самый правый недоверенный адрес из X-Forwarded-For / Forwarded IP непосредственного узла
REMOTE_PORT Исходный порт клиента из Forwarded: for=ip:port, иначе 0 Порт непосредственного узла
HTTPS "on", если X-Forwarded-Proto: https Устанавливается только когда соединение с узлом использует TLS
REQUEST_SCHEME "https" / "http" из X-Forwarded-Proto На основе фактического состояния TLS
SERVER_NAME Часть с именем хоста из X-Forwarded-Host Часть с именем хоста из заголовка Host
SERVER_PORT X-Forwarded-Port, иначе часть с портом из X-Forwarded-Host, иначе 443/80 по схеме Часть с портом из Host, либо 443/80

Исходные ключи HTTP_X_FORWARDED_FOR, HTTP_X_FORWARDED_PROTO, HTTP_X_FORWARDED_HOST, HTTP_X_FORWARDED_PORT и HTTP_FORWARDED остаются в $_SERVER без изменений — доступны и перезаписанные значения, и исходные заголовки.

REMOTE_PORT равен "0" за доверенным прокси, если только прокси не присылает RFC 7239 Forwarded: for=ip:port — ни X-Forwarded-For, ни выбор самого правого недоверенного адреса не несут исходного порта клиента, поэтому синтетическое значение обнуляется, а не угадывается.

Когда TRUSTED_PROXIES не задан, перезапись не выполняется, и REMOTE_ADDR всегда равен непосредственному узлу — обычно это ваш балансировщик нагрузки, а не конечный клиент. Разбирать X-Forwarded-For вручную чревато ошибками (крайний левый или крайний правый адрес, отсутствие проверки доверия по CIDR); предпочтительнее настроить TRUSTED_PROXIES. См. Доверенные прокси, где описаны алгоритм доверия и синтаксис настройки.

Переменные контекста трассировки

Когда включена распределённая трассировка, OxPHP добавляет в $_SERVER переменные контекста трассировки:

Переменная Описание Пример
OXPHP_TRACE_ID Идентификатор трассировки W3C для текущего запроса 4bf92f3577b34da6a3ce929d0e0e4736
OXPHP_SPAN_ID Идентификатор спана для серверного спана OxPHP 00f067aa0ba902b7
OXPHP_PARENT_SPAN_ID Идентификатор родительского спана от вышестоящего сервиса (пусто, если это корень) b9c7c989f97918e1

Эти переменные присутствуют только когда приходит корректный заголовок traceparent или когда OxPHP генерирует новую трассировку. Если трассировка не настроена, эти ключи отсутствуют.

Отличия от PHP-FPM

Следующие переменные ведут себя иначе, чем в стандартной конфигурации PHP-FPM:

Переменная Поведение
SERVER_ADDR Не устанавливается. OxPHP не заполняет локальный IP-адрес сервера.
PATH_INFO Устанавливается автоматически — см. Поведение PATH_INFO ниже.
PATH_TRANSLATED Не устанавливается.
PHP_AUTH_USER / PHP_AUTH_PW / AUTH_TYPE Не извлекаются из заголовка Authorization. Читайте $_SERVER['HTTP_AUTHORIZATION'] напрямую.
REDIRECT_STATUS Не устанавливается. OxPHP не использует внутренний механизм перенаправления.

Пример

php
<?php $method = $_SERVER['REQUEST_METHOD']; $uri = $_SERVER['REQUEST_URI']; $ip = $_SERVER['REMOTE_ADDR']; $host = $_SERVER['SERVER_NAME']; $scheme = $_SERVER['REQUEST_SCHEME']; // "http" or "https" // Read a custom header $token = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; // REMOTE_ADDR is already the real client IP when TRUSTED_PROXIES is configured. // Without it, REMOTE_ADDR is the direct peer (usually a load balancer). $clientIp = $_SERVER['REMOTE_ADDR']; // Check TLS without checking the port if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') { // Secure connection }

Поведение PATH_INFO

$_SERVER['PATH_INFO'] заполняется автоматически в зависимости от активного режима маршрутизации. Никакого флага для этого нет — прежняя переменная окружения SPLIT_PATH_INFO_ENABLED была удалена.

Режим маршрутизации Когда устанавливается Значение
Traditional (ENTRY_FILE не задан) Только когда URI содержит .php/ и префикс скрипта существует на диске Хвост после сегмента скрипта
Framework (ENTRY_FILE=index.php) Только когда запрос явно указывает входной файл с завершающим сегментом (/index.php/extra) Хвост после входного файла, например /news
SPA (ENTRY_FILE=index.html) Никогда — PHP выполняется только для точных .php-файлов, без PATH_INFO

SCRIPT_NAME всегда указывает на исполняемый скрипт (разрешённый файл относительно корневого каталога документов), поэтому при обычной маршрутизации PATH_INFO присутствует только тогда, когда SCRIPT_NAME является буквальным префиксом пути запроса. Когда запрос переписывается на фронт-контроллер, который в нём не назван (маршрут приложения, индекс каталога, запасной вариант при промахе по статике), PATH_INFO отсутствует, а исходный путь хранится в REQUEST_URI. (Запасной вариант PHP_DENY_PATHS — намеренное исключение: он устанавливает PATH_INFO равным исходному очищенному URI, чтобы запасной скрипт мог по нему маршрутизировать.)

Примеры режима Traditional

OxPHP сканирует URI слева направо в поисках первого сегмента .php, которому соответствует реальный файл на диске. Всё, что идёт после него, становится PATH_INFO:

URI запроса Файл на диске SCRIPT_NAME PATH_INFO PHP_SELF
/app.php/user/42 app.php существует /app.php /user/42 /app.php/user/42
/index.php/api/v2/users index.php существует /index.php /api/v2/users /index.php/api/v2/users
/app.php app.php существует /app.php (отсутствует) /app.php
/missing.php/foo файл не найден откат к /index.php зависит от отката

Примеры режима Framework

Каждый нестатический запрос переписывается на index.php. PATH_INFO устанавливается только тогда, когда запрос явно указывает входной файл с завершающим сегментом; для маршрутов приложения исходный путь читается из REQUEST_URI.

URI запроса SCRIPT_NAME PATH_INFO
/api/users /index.php (отсутствует)
/about.php /index.php (отсутствует)
/index.php/news/local /index.php /news/local
/index.php /index.php (отсутствует)
Note

PATH_TRANSLATED не заполняется. На практике он используется редко и по умолчанию не устанавливается ни nginx, ни PHP-FPM.

$_GET

Параметры строки запроса автоматически разбираются из URI запроса.

php
<?php // Request: GET /search?q=oxphp&page=2 $query = $_GET['q']; // "oxphp" $page = $_GET['page']; // "2"

Синтаксис массивов работает как ожидается:

php
<?php // Request: GET /filter?tags[]=php&tags[]=async $tags = $_GET['tags']; // ["php", "async"]

$_POST

OxPHP поддерживает два стандартных типа содержимого для отправки форм:

  • application/x-www-form-urlencoded — стандартные данные HTML-формы
  • multipart/form-data — загрузка файлов в сочетании с полями формы
php
<?php // Request: POST /login // Content-Type: application/x-www-form-urlencoded // Body: username=admin&password=secret $username = $_POST['username']; // "admin" $password = $_POST['password']; // "secret"

Для JSON или других типов содержимого используйте вместо этого php://input:

php
<?php // Request: POST /api/users // Content-Type: application/json // Body: {"name":"Alice","email":"alice@example.com"} $data = json_decode(file_get_contents('php://input'), true); $name = $data['name']; // "Alice" $email = $data['email']; // "alice@example.com"

Куки разбираются из заголовка запроса Cookie.

php
<?php // Request with: Cookie: session=abc123; theme=dark $session = $_COOKIE['session']; // "abc123" $theme = $_COOKIE['theme']; // "dark"
Note

Куки с префиксом __oxp_ зарезервированы для внутренних плагинов OxPHP. Они удаляются из заголовка Cookie до того, как он достигнет PHP, и не появляются в $_COOKIE.

$_FILES

Загруженные файлы, отправленные через multipart/form-data, заполняют массив $_FILES стандартной для PHP структурой:

php
<?php // $_FILES['avatar'] structure: // [ // 'name' => 'photo.jpg', // Original filename sent by the client // 'type' => 'image/jpeg', // MIME type declared by the client // 'tmp_name' => '/tmp/phpAb12Cd', // Temporary file path on the server // 'error' => 0, // UPLOAD_ERR_OK (0 means no error) // 'size' => 204800, // File size in bytes // ] if ($_FILES['avatar']['error'] === UPLOAD_ERR_OK) { $tmp = $_FILES['avatar']['tmp_name']; $name = basename($_FILES['avatar']['name']); move_uploaded_file($tmp, "/uploads/$name"); }

$_REQUEST

$_REQUEST — это объединённый массив из $_GET, $_POST и, опционально, $_COOKIE, формируемый PHP согласно INI-директиве request_order (по умолчанию: "GP" — сначала GET, затем POST). OxPHP не изменяет это поведение.

php
<?php // GET /form?action=preview with POST body: action=submit $action = $_REQUEST['action']; // "submit" (POST overrides GET with default order)

php://input

Необработанное тело запроса доступно через поток php://input. Это стандартный способ читать полезную нагрузку JSON, XML или любой тип содержимого, отличный от отправки форм.

php
<?php $body = file_get_contents('php://input'); $data = json_decode($body, true);

php://input можно перематывать и читать несколько раз в рамках одного запроса.

Note

php://input пуст для запросов multipart/form-data. Для них используйте $_POST и $_FILES.

Отключение суперглобальных переменных

Задайте SUPERGLOBALS_ENABLED=false, чтобы отключить заполнение $_GET, $_POST, $_COOKIE, $_FILES и $_SERVER. Когда отключено, эти массивы пусты. Для доступа к данным запроса используйте вместо этого HTTP Request API (oxphp_http_request()).

bash
SUPERGLOBALS_ENABLED=false # superglobals are empty arrays

Следующее остаётся доступным независимо от этой настройки:

Что Почему
$_SESSION Управляется модулем сессий PHP, а не SAPI
php://input Поток, а не суперглобальная переменная
header(), headers_list() и т. д. Функции SAPI, а не суперглобальные переменные
session_start() и другие функции session_*() Нативные функции PHP
oxphp_http_request() Всегда доступна — рекомендуемая альтернатива

Текущую настройку можно проверить во время выполнения:

php
if (!oxphp_superglobals_enabled()) { $request = oxphp_http_request(); $page = $request->query('page', 1); }

См. также

  • HTTP Request API -- типизированный, лениво загружаемый объект запроса как альтернатива суперглобальным переменным
  • Функции PHP -- oxphp_request_id(), oxphp_worker_id() и другие функции расширения
  • Режим воркеров -- как суперглобальные переменные обновляются между запросами воркера
  • Справочник по конфигурации -- DOCUMENT_ROOT и другие переменные конфигурации сервера