预定义变量

PHP 为所有脚本提供大量预定义变量。这些变量代表从 外部变量 到内置环境变量、最后一条错误消息到最后检索的标头的一切。

目录

添加注释

用户贡献的注释 25 个注释

26
josh,endquote,com
20 年前
在 Windows XP 上的 IIS 5 下运行 PHP 4.3,没有 $_SERVER['REQUEST_URI'] 变量。这似乎可以解决它

if(!isset($_SERVER['REQUEST_URI'])) {
$_SERVER['REQUEST_URI'] = substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1);
}
30
New York PHP
19 年前
警告:$_SERVER['PHP_SELF'] 可能包含任意用户输入。文档应更新以反映这一点。

请求 "http://example.com/info.php/attack%20here" 将运行 /info.php,但在 Apache 中,$_SERVER['PHP_SELF'] 将等于 "/info.php/attack here"。这是一个特性,但这意味着 PHP_SELF 必须被视为用户输入。

攻击字符串可能包含 URL 编码的 HTML 和 JavaScript(跨站点脚本),或者可能包含 URL 编码的换行符(HTTP 响应拆分)。

建议改用 $_SERVER['SCRIPT_NAME']。
15
nathan
18 年前
此外,关于使用 IP 来查找国家和城市,请注意您获得的结果可能并不完全准确。如果他们的 ISP 位于不同的城市或省份/州,则 IP 可能归总部所有,并在多个地区使用。
您还可能遇到更罕见的情况,即他们在旅途中、在工作中、在朋友家中 SSH 到另一台服务器……这是一个好主意,但如示例代码所示,它只应用于设置默认值。
9
Joe Marty
17 年前
我认为必须注意的是,PHP 将自动将点('.')和空格(' ')替换为下划线('_')在任何传入的 POST 或 GET(或 REQUEST)变量中。

此页面提到了点替换,但没有提到空格替换
http://us2.php.net/manual/en/language.variables.external.php

原因是 '.' 和 ' ' 不是在变量名中使用的有效字符。这对许多人来说很困惑,因为大多数人使用 $_POST['name'] 格式访问这些值。在这种情况下,name 不是用作变量名,而是用作数组索引,在这种情况下,这些字符是有效的。

但是,如果 register_globals 指令被设置,则这些名称必须用作变量名。到目前为止,PHP 在将这些变量插入外部变量数组之前会转换它们的名称,不幸的是 - 而不是将它们保留在数组中,只更改由 register_globals 设置的变量的名称。

如果您想使用
<input name="title for page3.php" type="text">

您将在 POST 数组中获得的值将是
$_POST['title_for_page3_php']
9
danvasile at pentest dot ro
17 年前
如果您在 $_SERVER['HTTPS'] 上遇到问题,特别是如果它根本没有返回任何值,您应该检查 phpinfo() 的结果。它可能根本没有列出。
以下是如何在所有情况下检查和更改为 ssl/https 的解决方案

<?php
if ($_SERVER['SERVER_PORT']!=443) {
$sslport=443; // 您的 ssl 端口是什么
$url = "https://". $_SERVER['SERVER_NAME'] . ":" . $sslport . $_SERVER['REQUEST_URI'];
header("Location: $url");
}
?>

当然,这应该在任何 html 标签或 php echo/print 之前完成。
9
youdontmeanmuch [at] yahoo.com
20 年前
在您希望将应用程序分发给其他具有不同服务器类型的人员的应用程序中,使用 $_SERVER['DOCUMENT_ROOT'] 时要小心。它并不总是受 Web 服务器(IIS)支持。
10
jameslporter at gmail dot com
18 年前
如果您没有在 $_SERVER[SERVER_NAME] 变量中获得 ServerName,请参考 CanonicalName……这对我很难解决……现在它通过启用规范命名按预期工作。

http://www.apacheref.com/ref/http_core/UseCanonicalName.html
8
Nicolae Namolovan
16 年前
安全风险!

永远不要相信来自 $_SERVER 的值。

HTTP_X_FORWARDED、HTTP_X_FORWARDED_FOR、HTTP_FORWARDED_FOR、HTTP_FORWARDED 等可以被欺骗!

要获取用户 IP,只使用 $_SERVER['REMOTE_ADDR'],否则用户的“IP”可以很容易地通过发送 HTTP_X_* 标头来更改,因此用户可以逃避封禁或欺骗受信任的 IP。

当然,这是众所周知的,但我没有看到它在这些注释中提到……

如果您只使用 IP 进行跟踪(而不是用于任何安全功能,如封禁或允许通过 IP 访问某些内容),您也可以使用 HTTP_X_FORWARDED 来获取在代理后面的用户的 IP。
6
daniel at softel dot jp
19 年前
请注意,$php_errormsg 可能包含换行符。如果您尝试使用 JavaScript "alert()" 等输出它,这可能会造成问题。
8
drew dot griffiths at clare dot net
18 年前
关于:您可以利用 404 错误进行可用的重定向,使用 REQUEST_URI……

虽然这很有效,但 .htaccess 中的一行,例如

RewriteEngine On
RewriteRule ^profiles/([A-Za-z0-9-]+) showprofile.php?profile=$1 [L,NC,QSA]

将把请求的配置文件放入 showprofile.php 页面的 $profile 变量中。

您可以进一步增强 URL(例如 http://servername/profiles/Jerry/homeaddress/index.htm),而第二个变量值 homeaddress 将在使用以下内容时在 $url_array[3] 中可用 $url_array=explode("/",$_SERVER['REQUEST_URI']);

希望这有帮助 - 对我来说效果很好

Drew
7
Aardvark
18 年前
$_GET 可能无法处理包含从将 JavaScript "escape" 函数应用于 Unicode 字符串生成的转义 Unicode 值的查询字符串参数值。
要处理这个问题,可以使用以下函数获取查询参数值

function getQueryParameter ($strParam) {
$aParamList = explode('&', $_SERVER['QUERY_STRING']);
$i = 0;
while ($i < count($aParamList)) {
$aParam = split('=', $aParamList[$i]);
if ($strParam == $aParam[0]) {
return $aParam[1];
}
}
return "";
}

或者直接构建数组或查询字符串值,然后使用函数(例如可在 http://www.kanolife.com/escape/2006/03/unicode-url-escapes-in-php.html(或 http://www.kanolife.com/escape/ 获取相关信息)中找到的 “unescape” 函数)处理参数字符串。
5
匿名
18 年前
我无法说服我的主机公司更改他们的 PHP 安装,因此不得不自己想办法计算 $_SERVER["DOCUMENT_ROOT"]。我最终找到了以下解决方案,它结合了之前笔记(并修正了一些拼写错误)

<?php
if ( ! isset($_SERVER['DOCUMENT_ROOT'] ) )
$_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr(
$_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF']) ) );
?>
5
[email protected]
19 年前
关于消息正文...没有任何内容

您可以获取 cookie、会话变量、标头、请求 URI、请求方法等,但无法获取消息正文。当您的页面需要使用 POST 方法请求时,您可能需要它。

也许他们应该提到 $HTTP_RAW_POST_DATA 或 php://stdin
4
Gregory Boshoff
19 年前
$_SERVER['QUERY_STRING']

不包含符合 XHTML 1.1 标准的 & 符号,即 &amp;

因此,如果要在 URL 中使用 $_SERVER['QUERY_STRING'],您需要执行类似以下的操作。

// 符合 XHTML 1.1 标准的 & 符号
$_SERVER['QUERY_STRING'] =
str_replace(array('&amp;', '&'), array('&', '&amp;'),
$_SERVER['QUERY_STRING']);
4
Gregory Boshoff
19 年前
环境变量 $ENV 可用于编写可移植的平台特定应用程序常量。

// 定义 Windows 或 Linux 根目录路径
$_ENV['OS'] == 'Windows_NT' ? $path = 'L:\\www\\' : $path = ' /var/www/';

define('PATH', $path);

echo PATH;
3
Ben XO
18 年前
因此,您在网络空间中有一个应用程序,其 URL 如下所示

http://<host>/<installation_path>/

以及诸如以下的页面

http://<host>/<installation_path>/subfolder1/subfolder2/page.php

您有一个名为 config.php 的文件位于 <installation_path> 中,该文件被所有页面(无论是在子文件夹中还是不在子文件夹中)包含。

如何在不将其硬编码到配置文件中的情况下计算出 <installation_path>?

<?php

// 这是 config.php,它位于 <installation_path> 中
// 它被 <installation_path>/page.php 包含
// 它被 <installation_path>/subfolder/page2.php 包含
// 等等

$_REAL_SCRIPT_DIR = realpath(dirname($_SERVER['SCRIPT_FILENAME'])); // 此页面的目录的系统路径(page.php)
$_REAL_BASE_DIR = realpath(dirname(__FILE__)); // 此文件的目录的系统路径(config.php)
$_MY_PATH_PART = substr( $_REAL_SCRIPT_DIR, strlen($_REAL_BASE_DIR)); // 仅 <installation_path> 和页面之间的子文件夹部分

$INSTALLATION_PATH = $_MY_PATH_PART
? substr( dirname($_SERVER['SCRIPT_NAME']), 0, -strlen($_MY_PATH_PART) )
:
dirname($_SERVER['SCRIPT_NAME'])
;
// 我们从 <installation_path> 的末尾减去子文件夹部分,只留下 <installation_path> :)

?>
2
[email protected]
14 年前
如果您尝试通过命令行运行 php,例如:php.exe c:\AppServ\www\cron_cache.php。最好避免使用 $_SERVER['DOCUMENT_ROOT'],因为它将返回空值。相反,您可以使用 dirname(__FILE__)。使用命令行运行 php 的原因是将其设置为 Windows 计划任务。我没有在 Linux 环境下测试,但可能相同。
3
[email protected]
19 年前
如果您使用 Apache 的重定向功能来创建自定义错误页面或其他用途,则以下 Apache 的 REDIRECT 变量也可以在 $_SERVER 中使用
$_SERVER['REDIRECT_UNIQUE_ID]'
$_SERVER['REDIRECT_SCRIPT_URL]'
$_SERVER['REDIRECT_SCRIPT_URI]'
$_SERVER['REDIRECT_SITE_ROOT]'
$_SERVER['REDIRECT_SITE_HTMLROOT]'
$_SERVER['REDIRECT_SITE_CGIROOT]'
$_SERVER['REDIRECT_STATUS]'
$_SERVER['REDIRECT_QUERY_STRING]'
$_SERVER['REDIRECT_URL]'

不过,我不确定这是否是完整的列表
2
[email protected]
16 年前
我对某些 _SERVER 变量似乎不存在感到有些沮丧,因此我搜索了一番,找到了答案:许多这些变量是由 Web 服务器提供的,并非所有 Web 服务器都提供相同的变量集。

我在此页面上找到了 Apache v1.3.29 和 IIS v5.1 之间的比较:http://koivi.com/apache-iis-php-server-array.php 对于进行跨平台开发的我们来说很有用。

在使用不同的浏览器进行实验时,我注意到一些 HTTP_* 变量会根据所使用的浏览器而出现或消失,或者在 Opera 的情况下,通过调整“用户模式”(允许您以纯文本形式查看页面的窗口小部件等)也会出现或消失。例如:在 IE 和 Opera 中,HTTP_KEEP_ALIVE 缺失,但在 Firefox 和 Mozilla 中存在,当我调整 Opera 的“用户模式”时,我看到了一些名为 HTTP_TE 和 HTTP_CACHE_CONTROL 的内容。

因此,您得到的内容取决于 Web 服务器和浏览器。

我确实看到了一个 IIS 提供的变量,该变量未在该列表中:REQUEST_TIME,它似乎采用 Unix 时间戳格式。

在研究这个问题时,我发现有很多人的 phpinfo() 页面是可见的,并在一些搜索引擎中被索引。对于那些想比那个比较 Apache 和 IIS 的网页更深入了解的人来说,查看其他人的 phpinfo() 页面可能会有用。您可以获取 PHP 版本以及他们使用的操作系统和 Web 服务器,以及所有 _SERVER 变量。我在 Dogpile 上搜索“phpinfo()”(带引号)时,发现信噪比最高:http://www.dogpile.com/
1
[email protected]
13 年前
我使用 HTTP_X_FORWARDED_FOR,因为我的 Web 服务器位于反向代理后面。
这可以变得安全
配置反向代理以阻止此字段,并正确覆盖它。
配置 Apache 服务器以仅接受来自反向代理的传入连接。
1
jsan
16 年前
@White-Gandalf:可以通过设置以下内容来控制此行为

UseCanonicalName On|Off

在他们的 Apache 配置中(至少在 *ix 平台上)。

On => $_SERVER['SERVER_NAME'] 是来自全局服务器或虚拟主机的 ServerName 变量,无论哪一个最靠近 PHP 应用程序。

Off => 客户端发送的 Host: 标头中的任何内容。
1
[email protected]
16 年前
除了 [email protected](2007-06-07 03:33)

如果您使用 Apache 模块 mod_rewrite 并希望设置一些环境变量,Apache 手册指出这些变量可以在 CGI 中使用 $ENV{VAR} 访问。在 PHP 中,您可能希望编写 $_ENV['VAR'] 来获取 VAR 的值,但您必须通过 $_SERVER 访问它,并且采用不同的方式

1. 示例:.htaccess 和 example.php

RewriteEngine on
RewriteRule ^?var1=([^;]*);var2=([^;]*)$ \
- [E=VAR1:$1,E=VAR2:$2]

<?php echo($_SERVER['VAR1']."\r\n"
.$_SERVER['VAR2']); ?>

2. 示例:.htaccess 和 index.php

RewriteEngine on
RewriteRule ^index\.php$ - [L]
RewriteRule ?var1=([^;]*);var2=([^;]*)$ \
index.php [E=VAR1:$1,E=VAR2:$2]

<?php echo($_SERVER['REDIRECT_VAR1']."\r\n"
.$_SERVER['REDIRECT_VAR2']); ?>

注意:如果任何 RewriteRule 匹配,则会进行内部重定向,然后重新启动(在最后一个定义的规则之后,或者在匹配的规则具有 L 标志之后立即重新启动),并再次检查整个规则集。对于内部重定向,每个定义的 VAR 都会获得一个 'REDIRECT_' 前缀,即 VAR1 将为 REDIRECT_VAR1,VAR2 将为 REDIRECT_VAR2。

当然,您可以(额外)重新定义原始 VAR

RewriteEngine on
RewriteRule ^index\.php$ \
- [E=VAR1:%{REDIRECT_VAR1},E=VAR2:%{REDIRECT_VAR2},L]
RewriteRule ?var1=([^;]*);var2=([^;]*)$ \
index.php [E=VAR1:$1,E=VAR2:$2]

这样,您将拥有 $_SERVER['REDIRECT_VAR*'] 和 $_SERVER['VAR*']。

***

给出的示例仅供说明,在任何情况下,它们都不打算满足您的需求。.htaccess 示例中的 “\<CRLF><SP>” 仅用于显示目的,它们不应出现在真实的 .htaccess 文件中。链接中的参数分隔符 ';' 也可以是 '&',但这可能会导致 HTML/XHTML 出现一些问题。有关此问题的更多信息,请参阅以下页面
- http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2
- http://www.w3.org/QA/2005/04/php-session
-1
[email protected]
18 年前
要快速简单地转换查询字符串参数值($_GET、$_REQUEST),其中包含应用 JavaScript “escape” 函数于 Unicode 字符串(%uNNNN%uNNNN%uNNNN)后产生的转义 Unicode 值,可以使用 PECL JSON 扩展

function JavaScript_Unicode_URL_2_Str($js_uni_str) {
$res = preg_replace('/%u([[:alnum:]]{4})/', '\\u\1', $js_uni_str);
$res = str_replace('"', '\"', $res); // 如果在 str "
$res = json_decode('["'.$res.'"]'); // 带有字符串元素的 JavaScript 数组
$res = $res[0];
$res = iconv('UTF-8', ini_get('default_charset'), $res);
return $res;
}
-5
justin.(nospam)[email protected]
18 年前
请注意,在循环中追加全局变量是一个非常非常糟糕的做法,除非您确实要在全局上下文中执行此操作。不久前,我用类似这样的代码片段挂起了我的服务器

<?php
$host
= $_SERVER['HTTP_HOST'];
$uri = rtrim($_SERVER['PHP_SELF'], "/\\");


$GLOBALS['SITE_ROOT'] = "http://$host$uri";

while (
$i < somenumber)
readfile($GLOBALS['SITE_ROOT'] = $GLOBALS['SITE_ROOT'] . '/this/file.php');
$i++
}
?>

虽然这是一种创建超长 URL 和破坏服务器的有趣且不寻常的方法,但这绝对是一个糟糕的主意。

(特别是考虑到该脚本与同类型脚本同时运行,因此 $GLOBALS['SITE_ROOT'] 中的值是未知的。)
-6
marcus at lastcraft dot com
19 年前
如果您正在运行 XDebug,则不会填充变量 $php_errormsg。
To Top