Superglobals
OxPHP populates every standard PHP superglobal before your script executes, matching the behavior PHP developers expect from a traditional server setup. Values are available from the first line of your code, with no initialization required.
$_SERVER
OxPHP builds $_SERVER from the incoming HTTP request following the CGI/1.1 specification. Process environment variables are imported first; CGI variables are set afterward, so request-specific values always override any colliding environment keys.
Standard variables
| Variable | Description | Example |
|---|---|---|
SCRIPT_FILENAME |
Absolute filesystem path to the PHP script being executed | /var/www/html/public/index.php |
DOCUMENT_ROOT |
Web root directory configured via DOCUMENT_ROOT env var |
/var/www/html/public |
SERVER_SOFTWARE |
Server identifier (carries the running OxPHP version) | OxPHP/0.10.0 |
SERVER_PROTOCOL |
Negotiated HTTP protocol version | HTTP/2 |
REQUEST_METHOD |
HTTP method | GET |
REQUEST_URI |
Full URI with query string | /app?page=2 |
SCRIPT_NAME |
Path of the executed script relative to DOCUMENT_ROOT — the front controller in Framework mode, not the request URI |
/index.php |
DOCUMENT_URI |
Alias for SCRIPT_NAME, for nginx/PHP-FPM compatibility |
/index.php |
PHP_SELF |
SCRIPT_NAME plus PATH_INFO when present, otherwise equal to SCRIPT_NAME |
/index.php/user/42 |
QUERY_STRING |
Query portion of the URI (empty string when absent) | page=2 |
SERVER_NAME |
Hostname from the Host header |
example.com |
SERVER_PORT |
Port from the Host header |
8080 |
REMOTE_ADDR |
Client IP address | 172.17.0.1 |
REMOTE_PORT |
Client port number | 54321 |
HTTPS |
Set to "on" when the connection uses TLS; absent otherwise |
on |
REQUEST_SCHEME |
"https" for TLS connections, "http" otherwise |
https |
CONTENT_TYPE |
Value of the Content-Type header (no HTTP_ prefix) |
application/json |
CONTENT_LENGTH |
Value of the Content-Length header (no HTTP_ prefix) |
128 |
REQUEST_TIME |
Unix timestamp (integer) when the request started | 1738800000 |
REQUEST_TIME_FLOAT |
Unix timestamp with microsecond precision | 1738800000.123456 |
GATEWAY_INTERFACE |
CGI version string | CGI/1.1 |
When the Host header is absent, SERVER_NAME defaults to localhost and SERVER_PORT defaults to 80 (or 443 for TLS).
HTTP request headers
All HTTP request headers are added to $_SERVER with an HTTP_ prefix. Header names are converted to uppercase with dashes replaced by underscores, following CGI/1.1 conventions:
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_COOKIEContent-Type and Content-Length appear without the HTTP_ prefix — as CONTENT_TYPE and CONTENT_LENGTH — as required by the CGI specification.
Behind a reverse proxy
When TRUSTED_PROXIES is configured and the request peer is in the trusted set, OxPHP rewrites the following $_SERVER keys from forwarded headers (X-Forwarded-* or RFC 7239 Forwarded):
| Variable | Value when peer is trusted | Value otherwise |
|---|---|---|
REMOTE_ADDR |
Rightmost untrusted address from X-Forwarded-For / Forwarded |
Direct peer IP |
REMOTE_PORT |
Client source port from Forwarded: for=ip:port, otherwise 0 |
Direct peer port |
HTTPS |
"on" when X-Forwarded-Proto: https |
Set only when the peer connection is TLS |
REQUEST_SCHEME |
"https" / "http" from X-Forwarded-Proto |
Based on actual TLS state |
SERVER_NAME |
Host portion of X-Forwarded-Host |
Host portion of the Host header |
SERVER_PORT |
X-Forwarded-Port, else port portion of X-Forwarded-Host, else 443/80 by scheme |
Port portion of Host, or 443/80 |
The raw HTTP_X_FORWARDED_FOR, HTTP_X_FORWARDED_PROTO, HTTP_X_FORWARDED_HOST, HTTP_X_FORWARDED_PORT, and HTTP_FORWARDED keys remain in $_SERVER unchanged — both the rewritten values and the original headers are available.
REMOTE_PORT is "0" behind a trusted proxy unless the proxy sends RFC 7239 Forwarded: for=ip:port — neither X-Forwarded-For nor the rightmost-non-trusted selection carry a client source port, so the synthetic value is zeroed rather than guessed.
When TRUSTED_PROXIES is not set, no rewriting occurs and REMOTE_ADDR is always the direct peer — typically your load balancer, not the end client. Parsing X-Forwarded-For manually is error-prone (leftmost vs rightmost, no CIDR trust check); prefer configuring TRUSTED_PROXIES. See Trusted Proxies for the trust algorithm and configuration syntax.
Trace context variables
When distributed tracing is enabled, OxPHP adds trace context variables to $_SERVER:
| Variable | Description | Example |
|---|---|---|
OXPHP_TRACE_ID |
W3C trace ID for the current request | 4bf92f3577b34da6a3ce929d0e0e4736 |
OXPHP_SPAN_ID |
Span ID for the OxPHP server span | 00f067aa0ba902b7 |
OXPHP_PARENT_SPAN_ID |
Parent span ID from the upstream service (empty if root) | b9c7c989f97918e1 |
These variables are only present when a valid traceparent header arrives or when OxPHP generates a new trace. If tracing is not configured, these keys are absent.
Differences from PHP-FPM
The following variables behave differently compared to a standard PHP-FPM setup:
| Variable | Behavior |
|---|---|
SERVER_ADDR |
Not set. OxPHP does not populate the local server IP address. |
PATH_INFO |
Set automatically — see PATH_INFO behavior below. |
PATH_TRANSLATED |
Not set. |
PHP_AUTH_USER / PHP_AUTH_PW / AUTH_TYPE |
Not extracted from the Authorization header. Read $_SERVER['HTTP_AUTHORIZATION'] directly. |
REDIRECT_STATUS |
Not set. OxPHP does not use an internal redirect mechanism. |
Example
<?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 behavior
$_SERVER['PATH_INFO'] is populated automatically based on the active routing mode. There is no feature flag — the previous SPLIT_PATH_INFO_ENABLED env variable has been removed.
| Routing mode | When set | Value |
|---|---|---|
Traditional (ENTRY_FILE unset) |
Only when the URI contains .php/ and the script prefix exists on disk |
Tail after the script segment |
Framework (ENTRY_FILE=index.php) |
Only when the request explicitly names the entry file with a trailing segment (/index.php/extra) |
Tail after the entry file, e.g. /news |
SPA (ENTRY_FILE=index.html) |
Never — PHP only runs for exact .php files, no PATH_INFO |
— |
SCRIPT_NAME always identifies the executed script (the resolved file relative to the document root), so in normal routing PATH_INFO is present only when SCRIPT_NAME is a literal prefix of the request path. When a request is rewritten to a front controller it does not name (an application route, a directory index, a static-miss fallback), PATH_INFO is absent and the original path lives in REQUEST_URI. (The PHP_DENY_PATHS fallback is a deliberate exception: it sets PATH_INFO to the original sanitized URI so the fallback script can route on it.)
Traditional mode examples
OxPHP scans the URI left-to-right for the first .php segment that corresponds to an actual file on disk. Everything after it becomes PATH_INFO:
| Request URI | File on disk | SCRIPT_NAME |
PATH_INFO |
PHP_SELF |
|---|---|---|---|---|
/app.php/user/42 |
app.php exists |
/app.php |
/user/42 |
/app.php/user/42 |
/index.php/api/v2/users |
index.php exists |
/index.php |
/api/v2/users |
/index.php/api/v2/users |
/app.php |
app.php exists |
/app.php |
(absent) | /app.php |
/missing.php/foo |
file not found | falls back to /index.php |
— | depends on fallback |
Framework mode examples
Every non-static request is rewritten onto index.php. PATH_INFO is set only when the request explicitly names the entry file with a trailing segment; for application routes the original path is read from REQUEST_URI.
| Request URI | SCRIPT_NAME |
PATH_INFO |
|---|---|---|
/api/users |
/index.php |
(absent) |
/about.php |
/index.php |
(absent) |
/index.php/news/local |
/index.php |
/news/local |
/index.php |
/index.php |
(absent) |
PATH_TRANSLATED is not populated. It is rarely used in practice and is not set by nginx or PHP-FPM by default.
$_GET
Query string parameters are parsed automatically from the request URI.
<?php
// Request: GET /search?q=oxphp&page=2
$query = $_GET['q']; // "oxphp"
$page = $_GET['page']; // "2"Array syntax works as expected:
<?php
// Request: GET /filter?tags[]=php&tags[]=async
$tags = $_GET['tags']; // ["php", "async"]$_POST
OxPHP supports the two standard content types for form submissions:
application/x-www-form-urlencoded— standard HTML form datamultipart/form-data— file uploads combined with form fields
<?php
// Request: POST /login
// Content-Type: application/x-www-form-urlencoded
// Body: username=admin&password=secret
$username = $_POST['username']; // "admin"
$password = $_POST['password']; // "secret"For JSON or other content types, use php://input instead:
<?php
// Request: POST /api/users
// Content-Type: application/json
// Body: {"name":"Alice","email":"[email protected]"}
$data = json_decode(file_get_contents('php://input'), true);
$name = $data['name']; // "Alice"
$email = $data['email']; // "[email protected]"$_COOKIE
Cookies are parsed from the Cookie request header.
<?php
// Request with: Cookie: session=abc123; theme=dark
$session = $_COOKIE['session']; // "abc123"
$theme = $_COOKIE['theme']; // "dark"Cookies with the __oxp_ prefix are reserved for internal OxPHP plugins. They are stripped from the Cookie header before it reaches PHP and will not appear in $_COOKIE.
$_FILES
File uploads sent via multipart/form-data populate the $_FILES array with the standard PHP structure:
<?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 is a merged array of $_GET, $_POST, and optionally $_COOKIE, built by PHP according to the request_order INI directive (default: "GP" — GET, then POST). OxPHP does not modify this behavior.
<?php
// GET /form?action=preview with POST body: action=submit
$action = $_REQUEST['action']; // "submit" (POST overrides GET with default order)php://input
The raw request body is available through the php://input stream. This is the standard way to read JSON payloads, XML, or any content type other than form submissions.
<?php
$body = file_get_contents('php://input');
$data = json_decode($body, true);php://input is rewindable and can be read multiple times within the same request.
php://input is empty for multipart/form-data requests. Use $_POST and $_FILES for those.
Disabling superglobals
Set SUPERGLOBALS_ENABLED=false to disable population of $_GET, $_POST, $_COOKIE, $_FILES, and $_SERVER. When disabled, these arrays are empty. Use the HTTP Request API (oxphp_http_request()) to access request data instead.
SUPERGLOBALS_ENABLED=false # superglobals are empty arraysThe following remain available regardless of this setting:
| What | Why |
|---|---|
$_SESSION |
Managed by PHP's session module, not by the SAPI |
php://input |
A stream, not a superglobal |
header(), headers_list(), etc. |
SAPI functions, not superglobals |
session_start() and other session_*() functions |
Native PHP functions |
oxphp_http_request() |
Always available — the recommended alternative |
You can check the current setting at runtime:
if (!oxphp_superglobals_enabled()) {
$request = oxphp_http_request();
$page = $request->query('page', 1);
}See also
- HTTP Request API -- typed, lazy-loading request object as an alternative to superglobals
- PHP Functions --
oxphp_request_id(),oxphp_worker_id(), and other extension functions - Worker Mode -- how superglobals are refreshed between worker requests
- Configuration Reference --
DOCUMENT_ROOTand other server configuration variables