超全局变量

OxPHP 会在你的脚本执行之前填充好每一个标准 PHP 超全局变量,与 PHP 开发者在传统服务器环境下所期望的行为完全一致。这些值从你代码的第一行起就可用,无需任何初始化。

$_SERVER

OxPHP 依照 CGI/1.1 规范,从传入的 HTTP 请求构建 $_SERVER。它会先导入进程的环境变量,再设置 CGI 变量,因此请求相关的值总是会覆盖任何与之冲突的环境变量键。

标准变量

变量 说明 示例
SCRIPT_FILENAME 正在执行的 PHP 脚本的绝对文件系统路径 /var/www/html/public/index.php
DOCUMENT_ROOT 通过 DOCUMENT_ROOT 环境变量配置的 Web 根目录 /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 存在 PATH_INFO 时为 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 连接使用 TLS 时设为 "on",否则不存在 on
REQUEST_SCHEME TLS 连接为 "https",否则为 "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 默认为 localhostSERVER_PORT 默认为 80(TLS 下为 443)。

HTTP 请求头

所有 HTTP 请求头都会以 HTTP_ 前缀添加到 $_SERVER 中。请求头名称会按照 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-TypeContent-Length 不带 HTTP_ 前缀——分别为 CONTENT_TYPECONTENT_LENGTH——这是 CGI 规范的要求。

反向代理之后

当配置了 TRUSTED_PROXIES 且请求的对端处于可信集合中时,OxPHP 会从转发头(X-Forwarded-* 或 RFC 7239 Forwarded)重写以下 $_SERVER 键:

变量 对端可信时的值 其他情况下的值
REMOTE_ADDR 来自 X-Forwarded-For / Forwarded 中最右侧的不可信地址 直连对端 IP
REMOTE_PORT 来自 Forwarded: for=ip:port 的客户端源端口,否则为 0 直连对端端口
HTTPS X-Forwarded-Proto: https 时为 "on" 仅当对端连接为 TLS 时设置
REQUEST_SCHEME 来自 X-Forwarded-Proto"https" / "http" 基于实际 TLS 状态
SERVER_NAME X-Forwarded-Host 的主机部分 Host 请求头的主机部分
SERVER_PORT X-Forwarded-Port,否则取 X-Forwarded-Host 的端口部分,否则按 scheme 取 443/80 Host 的端口部分,或 443/80

原始的 HTTP_X_FORWARDED_FORHTTP_X_FORWARDED_PROTOHTTP_X_FORWARDED_HOSTHTTP_X_FORWARDED_PORTHTTP_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 追踪 ID 4bf92f3577b34da6a3ce929d0e0e4736
OXPHP_SPAN_ID OxPHP 服务器 span 的 Span ID 00f067aa0ba902b7
OXPHP_PARENT_SPAN_ID 来自上游服务的父 span ID(若为根则为空) b9c7c989f97918e1

只有在收到有效的 traceparent 请求头,或 OxPHP 生成了一个新的 trace 时,这些变量才会存在。如果未配置追踪,这些键将不存在。

与 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/ 且脚本前缀在磁盘上存在时 脚本段之后的尾部
FrameworkENTRY_FILE=index.php 仅当请求显式指定入口文件并带有尾部段时(/index.php/extra 入口文件之后的尾部,例如 /news
SPAENTRY_FILE=index.html 永不设置——PHP 只为精确匹配的 .php 文件运行,无 PATH_INFO

SCRIPT_NAME 始终标识被执行的脚本(相对于文档根目录解析出的文件),因此在正常路由下,只有当 SCRIPT_NAME 是请求路径的字面前缀时,PATH_INFO 才存在。当请求被重写到一个它并未指名的前端控制器时(应用路由、目录索引、静态文件未命中回退),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":"[email protected]"} $data = json_decode(file_get_contents('php://input'), true); $name = $data['name']; // "Alice" $email = $data['email']; // "[email protected]"

Cookie 会从 Cookie 请求头中解析。

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

带有 __oxp_ 前缀的 Cookie 保留给 OxPHP 内部插件使用。它们会在 Cookie 请求头到达 PHP 之前被剥离,不会出现在 $_COOKIE 中。

$_FILES

通过 multipart/form-data 发送的文件上传会以标准 PHP 结构填充 $_FILES 数组:

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 根据 request_order INI 指令构建(默认为 "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 可倒回(rewindable),在同一请求内可多次读取。

Note

对于 multipart/form-data 请求,php://input 为空。这类请求请使用 $_POST$_FILES

禁用超全局变量

设置 SUPERGLOBALS_ENABLED=false 可禁用对 $_GET$_POST$_COOKIE$_FILES$_SERVER 的填充。禁用后,这些数组为空。请改用 HTTP 请求 APIoxphp_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 请求 API —— 类型化、惰性加载的请求对象,作为超全局变量的替代方案
  • PHP 函数 —— oxphp_request_id()oxphp_worker_id() 及其他扩展函数
  • 工作进程模式 —— 工作进程各次请求之间如何刷新超全局变量
  • 配置参考 —— DOCUMENT_ROOT 及其他服务器配置变量