Skip to content

4.2 可变变量、预定义变量

在 PHP 中,有两种特殊类型的变量:可变变量和预定义变量。本文将详细介绍这两种变量的使用方法。

1. 可变变量

可变变量是一种特殊的变量,其变量名可以动态变化。在 PHP 中,通过在变量名前添加额外的 $ 符号来创建可变变量。

1.1 基本语法

php
$$variable_name = value;

1.2 示例

php
// 基本用法
$var = "name";
$$var = "John";
echo $name;  // 输出: John

// 多层可变变量
$a = "b";
$b = "c";
$c = "Hello";
echo $a;     // 输出: b
echo $$a;    // 输出: c
echo $$$a;   // 输出: Hello

// 在数组中使用
$array = ["key" => "value"];
$key = "array";
echo $$key["key"];  // 输出: value

// 在对象中使用
$obj = new stdClass();
$obj->name = "John";
$prop = "name";
echo $obj->$prop;  // 输出: John

1.3 注意事项

  • 可读性:过度使用可变变量会降低代码的可读性
  • 调试难度:可变变量使代码更难调试
  • 性能:可变变量的性能略低于普通变量
  • 安全性:如果变量名来自用户输入,可能存在安全风险

2. 预定义变量

PHP 提供了许多预定义变量,这些变量在脚本运行时自动创建,用于获取各种信息。

2.1 超全局变量

超全局变量是在全局作用域中可用的变量,无需使用 global 关键字即可在函数内部访问。

2.1.1 $_GET

用于获取通过 GET 方法提交的参数。

php
// 访问 URL: http://example.com?name=John&age=30
$name = $_GET['name'];  // "John"
$age = $_GET['age'];    // "30"

// 安全使用
$name = isset($_GET['name']) ? $_GET['name'] : 'Guest';
// 或使用 null 合并运算符
$name = $_GET['name'] ?? 'Guest';

2.1.2 $_POST

用于获取通过 POST 方法提交的参数。

php
// 处理表单提交
$username = $_POST['username'];
$password = $_POST['password'];

// 安全使用
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';

2.1.3 $_REQUEST

用于获取通过 GET、POST 和 COOKIE 方法提交的参数。

php
// 获取参数,优先顺序:POST > GET > COOKIE
$id = $_REQUEST['id'];

2.1.4 $_SESSION

用于存储和获取会话变量。

php
// 启动会话
session_start();

// 设置会话变量
$_SESSION['user_id'] = 1;
$_SESSION['username'] = 'John';

// 获取会话变量
echo $_SESSION['username'];

// 销毁会话变量
unset($_SESSION['user_id']);

// 销毁所有会话
session_destroy();

用于获取 COOKIE 变量。

php
// 获取 COOKIE
$user_id = $_COOKIE['user_id'] ?? '';

// 设置 COOKIE
setcookie('user_id', 1, time() + 3600);

2.1.6 $_SERVER

用于获取服务器和执行环境信息。

php
// 常用服务器信息
echo $_SERVER['SERVER_NAME'];     // 服务器名称
echo $_SERVER['SERVER_PORT'];     // 服务器端口
echo $_SERVER['REQUEST_URI'];     // 请求 URI
echo $_SERVER['HTTP_HOST'];       // 主机名
echo $_SERVER['HTTP_USER_AGENT']; // 用户代理
echo $_SERVER['REMOTE_ADDR'];     // 客户端 IP
echo $_SERVER['PHP_SELF'];        // 当前脚本路径
echo $_SERVER['REQUEST_METHOD'];  // 请求方法(GET/POST)

2.1.7 $_FILES

用于获取上传文件的信息。

php
// 处理文件上传
if (isset($_FILES['file'])) {
    $file = $_FILES['file'];
    $name = $file['name'];
    $tmp_name = $file['tmp_name'];
    $size = $file['size'];
    $error = $file['error'];
    
    if ($error === UPLOAD_ERR_OK) {
        move_uploaded_file($tmp_name, 'uploads/' . $name);
        echo '文件上传成功';
    }
}

2.1.8 $_ENV

用于获取环境变量。

php
// 获取环境变量
echo $_ENV['PATH'];
echo $_ENV['PHP_HOME'];

2.2 其他预定义变量

2.2.1 $GLOBALS

包含所有全局变量的数组。

php
// 访问全局变量
$GLOBALS['name'] = 'John';
echo $GLOBALS['name'];

2.2.2 $_GLOBALS

$GLOBALS 的别名。

2.2.3 $php_errormsg

包含最后一个错误信息。

php
// 启用 track_errors
ini_set('track_errors', 1);

// 产生错误
@$undefined_var;
echo $php_errormsg;

2.2.4 $HTTP_*_VARS

超全局变量的旧版本,已被废弃。

3. 可变变量与预定义变量的结合使用

3.1 动态访问超全局变量

php
$method = 'GET';
$param_name = 'id';
$value = $_GET[$param_name];  // 常规方式

// 使用可变变量
$super_global = '_' . $method;
$value = $$super_global[$param_name];  // 动态方式

3.2 动态设置会话变量

php
$session_key = 'user_id';
$session_value = 1;

// 使用可变变量
$session_var = '_SESSION';
$$session_var[$session_key] = $session_value;

// 常规方式
$_SESSION[$session_key] = $session_value;

4. 安全考虑

4.1 输入验证

  • 永远验证用户输入:无论是通过 GET、POST 还是 COOKIE 提交的数据
  • 使用过滤函数filter_input()filter_var()
  • 避免直接使用用户输入:特别是在 SQL 查询、文件操作等场景

4.2 防止注入攻击

  • SQL 注入:使用预处理语句或参数化查询
  • XSS 攻击:使用 htmlspecialchars() 转义输出
  • 命令注入:使用 escapeshellarg()escapeshellcmd()

4.3 示例:安全处理用户输入

php
// 安全获取 GET 参数
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false) {
    // 处理无效 ID
    $id = 1; // 默认值
}

// 安全获取 POST 参数
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

// 安全输出
$username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
echo "欢迎你,$username";

5. 最佳实践

5.1 可变变量使用建议

  • 谨慎使用:只在必要时使用可变变量
  • 提高可读性:为可变变量添加注释,说明其用途
  • 避免嵌套:尽量避免多层可变变量,如 $$$var
  • 安全使用:确保变量名来源安全,避免用户输入直接作为变量名

5.2 预定义变量使用建议

  • 使用合适的超全局变量:根据请求方式选择 $_GET$_POST
  • 安全处理:始终验证和过滤用户输入
  • 使用 null 合并运算符:简化空值处理,如 $var = $_GET['var'] ?? 'default'
  • 避免使用 $_REQUEST:可能导致意外的参数覆盖
  • 合理使用会话:不要在会话中存储过多数据

5.3 性能考虑

  • 缓存常用值:对于频繁访问的超全局变量,考虑缓存到局部变量
  • 减少访问次数:减少对超全局变量的重复访问
  • 使用 isset():在访问可能不存在的参数前使用 isset() 检查

6. 示例:综合使用

php
<?php
// 启动会话
session_start();

// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 安全获取表单数据
    $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
    $password = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);
    
    // 模拟登录验证
    if ($username === 'admin' && $password === '123456') {
        // 设置会话变量
        $_SESSION['user'] = [
            'username' => $username,
            'role' => 'admin'
        ];
        
        // 重定向到首页
        header('Location: index.php');
        exit;
    } else {
        $error = '用户名或密码错误';
    }
}

// 检查登录状态
$is_logged_in = isset($_SESSION['user']);

// 使用可变变量动态访问超全局变量
$request_method = $_SERVER['REQUEST_METHOD'];
$super_global = '_' . $request_method;
$params = $$super_global;

echo "请求方法:$request_method<br>";
echo "请求参数:";
print_r($params);
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <h1>用户登录</h1>
    
    <?php if (isset($error)): ?>
        <p style="color: red;"><?php echo $error; ?></p>
    <?php endif; ?>
    
    <form method="post">
        <label for="username">用户名:</label>
        <input type="text" id="username" name="username" required><br><br>
        
        <label for="password">密码:</label>
        <input type="password" id="password" name="password" required><br><br>
        
        <button type="submit">登录</button>
    </form>
    
    <?php if ($is_logged_in): ?>
        <p>你已登录,欢迎 <?php echo $_SESSION['user']['username']; ?></p>
    <?php endif; ?>
</body>
</html>

7. 总结

可变变量和预定义变量是 PHP 中两种特殊的变量类型:

  • 可变变量:允许动态创建和访问变量,增加了代码的灵活性,但也可能降低可读性和安全性
  • 预定义变量:提供了访问请求数据、服务器信息等的便捷方式,是 PHP 与外部世界交互的重要桥梁

合理使用这两种变量,可以编写更加灵活、强大的 PHP 代码。但同时要注意安全问题,始终验证和过滤用户输入,防止注入攻击。

© 2026 编程马·菜鸟教程 版权所有