Appearance
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; // 输出: John1.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();2.1.5 $_COOKIE
用于获取 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 代码。但同时要注意安全问题,始终验证和过滤用户输入,防止注入攻击。
