Skip to content

PHP 超全局变量

超全局变量(Superglobals)是 PHP 中的内置变量,它们在所有作用域内始终可用。你可以在任何函数、类或文件中访问它们,而无需声明为全局变量或将其作为参数传递。

PHP 提供了几个预定义的超全局变量:

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

本章将探讨一些最常用的超全局变量。其他变量,如 $_SESSION、$_COOKIE 和 $_FILES,通常会在与会话、Cookie 和文件上传相关的章节中更详细地介绍。

$GLOBALS 是一个关联数组,包含当前在全局作用域中定义的所有变量的引用。此数组的键是全局变量的名称。

这允许你在函数或方法等局部作用域内访问全局变量。

示例:

<?php
$x = 75;
$y = 25;
function addition() {
// 使用 $GLOBALS 访问全局变量 $x 和 $y
// 并将结果存储在新的全局变量 $z 中
$GLOBALS['z'] = $GLOBALS['x'] + $GLOBALS['y'];
}
addition();
echo "The sum is: " . $z; // 访问全局定义的 $z
?>

输出:

The sum is: 100

注意: 尽管 $GLOBALS 提供了访问全局变量的方式,但过度依赖它可能导致代码难以维护和调试。它会使函数与全局状态紧密耦合。考虑将变量作为函数参数传递或使用依赖注入来获得更好的代码结构。

$_SERVER 是一个包含头信息、路径和脚本位置等信息的数组。此数组中的条目由 Web 服务器创建。不能保证每个 Web 服务器都会提供所有这些条目;服务器可能会省略一些,或提供此处未列出的其他条目。

示例:

<?php
echo 'Script Filename: ' . htmlspecialchars($_SERVER['PHP_SELF']) . "<br>";
echo 'Server Name: ' . htmlspecialchars($_SERVER['SERVER_NAME']) . "<br>";
echo 'HTTP Host: ' . htmlspecialchars($_SERVER['HTTP_HOST']) . "<br>";
// HTTP_REFERER 并非总是可靠或存在
echo 'HTTP Referer: ' . (isset($_SERVER['HTTP_REFERER']) ? htmlspecialchars($_SERVER['HTTP_REFERER']) : 'N/A') . "<br>";
echo 'User Agent: ' . htmlspecialchars($_SERVER['HTTP_USER_AGENT']) . "<br>";
echo 'Script Name: ' . htmlspecialchars($_SERVER['SCRIPT_NAME']) . "<br>";
echo 'Request Method: ' . htmlspecialchars($_SERVER['REQUEST_METHOD']) . "<br>";
echo 'Remote Address: ' . htmlspecialchars($_SERVER['REMOTE_ADDR']) . "<br>";
?>

常用 $_SERVER 元素:

元素/代码描述
$_SERVER['PHP_SELF']当前正在执行脚本的文件名,相对于文档根目录。直接在 HTML 中输出时要小心(参见下面的安全注意)。
$_SERVER['GATEWAY_INTERFACE']服务器正在使用的通用网关接口 (CGI) 版本。
$_SERVER['SERVER_ADDR']当前脚本正在其下执行的服务器 IP 地址。
$_SERVER['SERVER_NAME']当前脚本正在其下执行的服务器主机名。(例如,‘www.example.com’)
$_SERVER['SERVER_SOFTWARE']服务器标识字符串(例如,‘Apache/2.4.41 (Ubuntu)‘)
$_SERVER['SERVER_PROTOCOL']信息协议的名称和修订版本(例如,‘HTTP/1.1’)。
$_SERVER['REQUEST_METHOD']访问页面所用的请求方法(例如,‘GET’、‘POST’、‘PUT’)。
$_SERVER['REQUEST_TIME_FLOAT']请求开始的时间戳,精确到微秒(浮点数)。
$_SERVER['REQUEST_TIME']请求开始的时间戳(整数)。
$_SERVER['QUERY_STRING']访问页面时通过的查询字符串,如果有的话。
$_SERVER['HTTP_HOST']当前请求中的 Host: 头信息内容。
$_SERVER['HTTP_REFERER']引导用户代理访问当前页面的页面地址(如果有的话)。不可靠,因为它取决于用户代理。
$_SERVER['HTTP_USER_AGENT']当前请求中的 User-Agent: 头信息内容。
$_SERVER['HTTPS']如果脚本是通过安全的 HTTPS 协议查询的,则设置为非空值。
$_SERVER['REMOTE_ADDR']用户查看当前页面所用的 IP 地址。如果位于代理之后可能不可靠。
$_SERVER['REMOTE_HOST']用户查看当前页面所用的主机名。可能需要进行 DNS 查找。
$_SERVER['REMOTE_PORT']用户机器上用于与 Web 服务器通信的端口。
$_SERVER['SCRIPT_FILENAME']当前正在执行脚本的绝对路径名。
$_SERVER['SERVER_PORT']Web 服务器用于通信的服务器机器上的端口(例如,‘80’、‘443’)。
$_SERVER['SCRIPT_NAME']包含当前脚本的路径。对于指向脚本本身的链接很有用。
$_SERVER['REQUEST_URI']访问此页面时提供的 URI(例如,‘/index.html’)。

关于 $_SERVER['PHP_SELF'] 的安全注意: 永远不要在未经 htmlspecialchars() 转义的情况下直接将 $_SERVER['PHP_SELF'] 输出到 HTML 属性中(如表单的 action)。否则可能导致跨站脚本 (XSS) 漏洞。详情请参见表单验证章节。

$_REQUEST 是一个关联数组,默认情况下包含 $_GET、$_POST 和 $_COOKIE 的内容。

虽然方便,但使用 $_REQUEST 有时会让人不清楚数据的来源(GET、POST 或 COOKIE),这可能带来安全隐患。通常建议在你已知数据提交方式时(例如通过表单方法或 URL 参数),使用更具体的 $_GET 或 $_POST 数组。

示例(演示访问方式,但推荐使用 $_POST 或 $_GET):

form.html
<html>
<body>
<form method="post" action="process.php">
Name: <input type="text" name="fname">
<input type="submit">
</form>
<a href="process.php?city=London">Send City via GET</a>
</body>
</html>
process.php
<?php
// 使用 $_REQUEST(不太具体)
if (isset($_REQUEST['fname'])) {
$name = htmlspecialchars($_REQUEST['fname']); // 清理输出
echo "Name submitted via POST (likely): " . $name . "<br>";
}
if (isset($_REQUEST['city'])) {
$city = htmlspecialchars($_REQUEST['city']); // 清理输出
echo "City submitted via GET (likely): " . $city . "<br>";
}
// 推荐方法:
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['fname'])) {
$name_post = htmlspecialchars($_POST['fname']);
echo "Using POST explicitly: Name = " . $name_post . "<br>";
}
if (isset($_GET['city'])) {
$city_get = htmlspecialchars($_GET['city']);
echo "Using GET explicitly: City = " . $city_get . "<br>";
}
?>

$_POST 是一个关联数组,包含在使用 application/x-www-form-urlencoded 或 multipart/form-data 作为 HTTP Content-Type 发送请求时,通过 HTTP POST 方法传递到当前脚本的变量。

它通常用于收集通过带有 method="post" 的 HTML 表单提交的数据。

示例:

<!-- post_form.php -->
<html>
<body>
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']);?>">
Name: <input type="text" name="username">
<input type="submit" value="Submit Name">
</form>
<?php
// 检查表单是否使用 POST 方法提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// 收集输入字段的值,应用基本输出转义
// 重要提示:实际应用需要强大的验证和清理!
$name = isset($_POST['username']) ? htmlspecialchars($_POST['username']) : '';
if (empty($name)) {
echo "<p style='color:red;'>Name is empty!</p>";
} else {
echo "<p>Hello, " . $name . "!</p>";
}
}
?>
</body>
</html>

当用户点击“Submit Name”时,表单数据会通过 POST 方法发送到同一个脚本(post_form.php)。PHP 代码块检查请求方法是否为 POST,然后使用 $_POST['username'] 访问提交的 ‘username’ 值。

$_GET 是一个关联数组,包含通过 URL 参数(查询字符串)传递到当前脚本的变量。

它通常用于检索通过带有 method="get" 的 HTML 表单发送的数据,或直接嵌入在超链接中的数据。

超链接示例:

page1.html
<html>
<body>
<a href="test_get.php?subject=PHP&topic=Superglobals">Test GET Request</a>
</body>
</html>

当用户点击链接时,浏览器会导航到 test_get.php,并将 subject 和 topic 作为 URL 参数发送。test_get.php 脚本可以使用 $_GET 访问这些值:

test_get.php
<?php
// 访问查询字符串中的值,应用基本输出转义
// 重要提示:实际应用需要强大的验证和清理!
$subject = isset($_GET['subject']) ? htmlspecialchars($_GET['subject']) : 'Default Subject';
$topic = isset($_GET['topic']) ? htmlspecialchars($_GET['topic']) : 'Default Topic';
echo "Studying " . $subject . " focusing on " . $topic . ".";
?>

输出:

Studying PHP focusing on Superglobals.

重要提示: 来自 $_GET、$_POST 和 $_REQUEST 的数据源于用户,切勿信任这些数据。在使用这些数据进行数据库查询、在 HTML 中显示或进一步处理之前,请务必对其进行验证和清理,以防止 XSS 和 SQL 注入等安全漏洞。示例中使用的 htmlspecialchars() 函数提供了基本的输出转义,但全面的验证至关重要。