PHP $_GET 变量

$_GET 是PHP中的一个超全局变量,用于收集通过URL参数或HTML表单(使用GET方法)发送的数据。本章节将详细介绍如何使用$_GET变量获取和处理数据,以及相关的安全考虑。

什么是 $_GET 变量?

$_GET 是一个PHP超全局变量,这意味着它在整个脚本中都是可用的,不需要在函数中声明为全局变量。$_GET 用于收集通过URL传递的数据,这些数据会显示在浏览器的地址栏中。

URL参数的格式通常是这样的:

http://example.com/page.php?name=John&age=25

在这个例子中,URL包含两个参数:nameage,其值分别为John25

如何访问 $_GET 变量

您可以通过关联数组的方式访问$_GET变量中的数据:

<?php
// 假设URL是:http://example.com/page.php?name=John&age=25

// 获取name参数
$name = $_GET["name"]; // 返回 "John"

// 获取age参数
$age = $_GET["age"]; // 返回 "25"

// 显示数据
 echo "欢迎您," . $name . "!您的年龄是 " . $age . " 岁。";
?>

使用 HTML 表单发送 GET 请求

您可以使用HTML表单的GET方法来向服务器发送数据:

<!DOCTYPE html>
<html>
<body>

<form action="welcome.php" method="get">
  名字: <input type="text" name="name">
  年龄: <input type="text" name="age">
  <input type="submit">
</form>

</body>
</html>

当用户点击提交按钮时,表单数据会通过URL发送到welcome.php页面:

http://example.com/welcome.php?name=John&age=25

然后,welcome.php页面可以使用$_GET变量来获取这些数据:

<?php
// welcome.php
$name = $_GET["name"];
$age = $_GET["age"];
echo "欢迎您," . $name . "!您的年龄是 " . $age . " 岁。";
?>

检查 $_GET 变量是否存在

在访问$_GET变量之前,始终应该检查它是否存在,以避免未定义索引错误:

<?php
if (isset($_GET["name"])) {
    $name = $_GET["name"];
    echo "欢迎您," . $name . "!";
} else {
    echo "请提供您的名字。";
}
?>

您也可以使用empty()函数来检查变量是否存在且不为空:

<?php
if (!empty($_GET["name"])) {
    $name = $_GET["name"];
    echo "欢迎您," . $name . "!";
} else {
    echo "请提供您的名字。";
}
?>

$_GET 的实际应用示例

$_GET变量在实际应用中有多种用途,以下是一些常见的示例:

1. 分页功能

<?php
// 从URL获取当前页码,如果不存在则默认为1
$page = isset($_GET["page"]) ? (int)$_GET["page"] : 1;

// 设置每页显示的记录数
$recordsPerPage = 10;

// 计算偏移量
$offset = ($page - 1) * $recordsPerPage;

// 查询数据库(示例)
// $sql = "SELECT * FROM products LIMIT $offset, $recordsPerPage";

// 显示分页链接
// echo "<a href='products.php?page=" . ($page - 1) . "'>上一页</a>";
// echo "<a href='products.php?page=" . ($page + 1) . "'>下一页</a>";
?>

2. 搜索功能

<?php
// HTML表单
// <form action="search.php" method="get">
//   <input type="text" name="query" placeholder="搜索...">
//   <input type="submit" value="搜索">
// </form>

if (isset($_GET["query"])) {
    $searchQuery = $_GET["query"];
    // 实际应用中应该对搜索查询进行安全处理
    $searchQuery = htmlspecialchars($searchQuery);
    
    echo "您搜索的内容是:" . $searchQuery;
    // 执行搜索操作(示例)
    // $sql = "SELECT * FROM products WHERE name LIKE '%" . $searchQuery . "%'";
}
?>

3. 排序功能

<?php
// 从URL获取排序字段和方向
$sortField = isset($_GET["sort"]) ? $_GET["sort"] : "id";
$sortDirection = isset($_GET["dir"]) && $_GET["dir"] == "desc" ? "desc" : "asc";

// 限制允许的排序字段以提高安全性
$allowedFields = ["id", "name", "price", "date"];
if (!in_array($sortField, $allowedFields)) {
    $sortField = "id";
}

// 构建排序查询(示例)
// $sql = "SELECT * FROM products ORDER BY $sortField $sortDirection";

// 显示排序链接
// echo "<a href='products.php?sort=name&dir=" . ($sortDirection == "asc" ? "desc" : "asc") . "'>按名称排序</a>";
?>

$_GET 变量的安全考虑

使用$_GET变量时,安全是一个重要的考虑因素,因为用户可以直接修改URL中的参数。以下是一些安全最佳实践:

1. 始终验证和清理用户输入

<?php
if (isset($_GET["id"])) {
    // 将输入转换为整数(适用于ID等数值)
    $id = (int)$_GET["id"];
    
    // 或者使用filter_var
    $id = filter_var($_GET["id"], FILTER_VALIDATE_INT);
    
    if ($id === false) {
        // 处理无效的ID
        echo "无效的ID";
    } else {
        // 使用验证后的ID
        // $sql = "SELECT * FROM products WHERE id = $id";
    }
}
?>

2. 防止XSS攻击

当显示用户输入的数据时,使用htmlspecialchars()函数来防止跨站脚本攻击:

<?php
if (isset($_GET["name"])) {
    // 清理输入以防止XSS攻击
    $name = htmlspecialchars($_GET["name"]);
    echo "欢迎您," . $name . "!";
}
?>

3. 防止SQL注入

当使用$_GET变量构建SQL查询时,始终使用预处理语句或参数化查询:

<?php
if (isset($_GET["id"])) {
    $id = (int)$_GET["id"];
    
    // 使用预处理语句(PDO示例)
    // $stmt = $pdo->prepare("SELECT * FROM products WHERE id = :id");
    // $stmt->bindParam(':id', $id, PDO::PARAM_INT);
    // $stmt->execute();
    // $product = $stmt->fetch();
}
?>

4. 限制访问敏感操作

不要使用GET请求来执行敏感操作,如删除记录或修改数据,因为:

  • GET请求会被浏览器历史记录保存
  • GET请求可以被书签保存
  • GET请求可以被搜索引擎索引
  • GET请求容易被 CSRF(跨站请求伪造)攻击利用

敏感操作应该使用POST请求:

<!-- 不安全的删除操作 -->
<a href="delete.php?id=123">删除</a>

<!-- 更安全的做法 -->
<form action="delete.php" method="post" onsubmit="return confirm('确定要删除吗?');">
    <input type="hidden" name="id" value="123">
    <button type="submit">删除</button>
</form>

$_GET 与 $_POST 的比较

GET和POST是向服务器提交数据的两种主要方式,它们之间有以下区别:

可以发送二进制数据(如文件)
特性 GET POST
数据可见性 数据显示在URL中 数据在HTTP请求体中,对用户不可见
数据长度限制 通常有长度限制(取决于浏览器) 没有明确的长度限制
数据类型 只能发送ASCII字符
缓存 可以被浏览器缓存 不会被缓存
书签 可以被添加为书签 不能被添加为书签
历史记录 会被保存在浏览器历史中 不会被保存在浏览器历史中
安全性 较低,不应用于敏感数据 较高,适合发送敏感数据
主要用途 获取数据、搜索、分页 提交表单、修改数据、上传文件

提示:虽然GET请求在某些方面不如POST安全,但这并不意味着GET请求不能用于任何需要安全的场景。关键在于,无论使用哪种请求方法,您都应该在服务器端对所有用户输入进行适当的验证和清理。

完整示例:使用 $_GET 构建搜索功能

以下是一个使用$_GET变量构建搜索功能的完整示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PHP搜索示例</title>
<style>
.search-container {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #f9fafb;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.search-form {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
}

.search-input {
    flex: 1;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 16px;
}

.search-button {
    padding: 10px 20px;
    background-color: #4F46E5;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
}

.search-button:hover {
    background-color: #4338CA;
}

.results {
    margin-top: 20px;
}

.result-item {
    padding: 15px;
    background-color: white;
    border: 1px solid #eee;
    border-radius: 4px;
    margin-bottom: 10px;
}

.result-title {
    font-weight: bold;
    color: #4F46E5;
    margin-bottom: 5px;
}

.no-results {
    text-align: center;
    color: #666;
    padding: 20px;
}
</style>
</head>
<body>

<div class="search-container">
    <h2>PHP搜索示例</h2>
    
    <!-- 搜索表单 -->
    <form class="search-form" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="get">
        <input type="text" class="search-input" name="query" placeholder="搜索产品..." value="<?php echo isset($_GET['query']) ? htmlspecialchars($_GET['query']) : '';?>">
        <button type="submit" class="search-button">搜索</button>
    </form>
    
    <!-- 搜索结果 -->
    <div class="results">
        <?php
        // 检查是否提交了搜索查询
        if (isset($_GET["query"])) {
            // 获取并清理搜索查询
            $searchQuery = htmlspecialchars($_GET["query"]);
            
            // 在实际应用中,这里应该查询数据库
            // 为了示例,我们使用模拟数据
            $products = array(
                array("id" => 1, "name" => "PHP基础教程", "description" => "适合初学者的PHP编程入门教程"),
                array("id" => 2, "name" => "PHP高级编程", "description" => "深入学习PHP面向对象编程和设计模式"),
                array("id" => 3, "name" => "PHP安全指南", "description" => "学习如何编写安全的PHP应用程序"),
                array("id" => 4, "name" => "JavaScript入门", "description" => "Web前端开发的JavaScript基础知识"),
                array("id" => 5, "name" => "HTML5 & CSS3教程", "description" => "现代Web页面设计与开发技术")
            );
            
            // 模拟搜索过程
            $matchingProducts = array();
            foreach ($products as $product) {
                if (stripos($product["name"], $searchQuery) !== false || 
                    stripos($product["description"], $searchQuery) !== false) {
                    $matchingProducts[] = $product;
                }
            }
            
            // 显示搜索结果
            if (count($matchingProducts) > 0) {
                echo "<p>找到 ".count($matchingProducts)." 个与'$searchQuery'相关的结果:</p>";
                foreach ($matchingProducts as $product) {
                    echo "<div class='result-item'>";
                    echo "<div class='result-title'>".htmlspecialchars($product["name"])."</div>";
                    echo "<div>".htmlspecialchars($product["description"])."</div>";
                    echo "</div>";
                }
            } else {
                echo "<div class='no-results'>没有找到与 '$searchQuery' 相关的结果。</div>";
            }
        }
        ?>
    </div>
</div>

</body>
</html>