You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP数据库重复分类检测代码咨询:是否存在遗漏?

代码问题分析与修正方案

Hey there, let's walk through the issues in your code and fix them up—there are some critical security and functionality gaps here:

1. 严重的SQL注入漏洞

直接将用户输入的$_POST['Add_category']拼接进SQL语句是极高风险的操作,攻击者可以通过构造恶意输入来篡改你的数据库(比如删除表、窃取数据)。必须使用参数化查询来避免这个问题,sqlsrv完全支持参数绑定。

2. 错误处理语法错误

你把OR die(sqlsrv_errors())写在了SQL字符串的末尾,这是语法错误——$query1是一个字符串,不能直接跟OR die()。错误处理应该放在sqlsrv_query调用之后,判断查询是否执行失败。

3. sqlsrv_num_rows无法正确获取行数(默认游标限制)

sqlsrv默认使用SQLSRV_CURSOR_FORWARD游标,这种游标不支持获取行数(sqlsrv_num_rows会返回false)。你需要在查询时指定支持行数统计的游标类型,比如SQLSRV_CURSOR_STATIC。

4. 逻辑顺序不合理

你先执行了数据库查询,再检查$newcategory是否为空。应该先做客户端的输入校验,避免不必要的数据库请求。

5. 错误处理不完整

当sqlsrv_query执行失败返回false时,后续的sqlsrv_num_rows($statement1)会触发新的错误,因为你不能对false调用这个函数。必须先判断查询成功,再处理结果。


修正后的完整代码

<?php
if (isset($_POST['create_new_category'])) {
    $newcategory = trim($_POST['Add_category']); // 先去除首尾空格

    // 第一步:先检查输入是否为空
    if (empty($newcategory)) {
        echo "请输入分类名称";
        exit; // 终止后续执行
    }

    // 第二步:参数化查询检查分类是否存在
    $query1 = "SELECT 1 FROM JobAdCategories WHERE jacat_title = ?";
    $params1 = array($newcategory);
    $options = array("Scrollable" => SQLSRV_CURSOR_STATIC); // 指定支持行数的游标
    $statement1 = sqlsrv_query($connection, $query1, $params1, $options);

    if ($statement1 === false) {
        echo "查询错误 (sqlsrv_query): " . print_r(sqlsrv_errors(), true);
        exit;
    }

    $count = sqlsrv_num_rows($statement1);
    sqlsrv_free_stmt($statement1); // 释放语句资源

    if ($count == 0) {
        // 第三步:参数化插入新分类
        $query2 = "INSERT INTO JobAdCategories (jacat_title) VALUES (?)";
        $params2 = array($newcategory);
        $statement2 = sqlsrv_query($connection, $query2, $params2);

        if ($statement2 === false) {
            echo "插入错误 (sqlsrv_query2): " . print_r(sqlsrv_errors(), true);
        } else {
            echo "新分类已成功添加";
            sqlsrv_free_stmt($statement2);
        }
    } else {
        echo "该分类已存在";
    }
}
?>

额外优化点

  • 添加了trim()去除输入的首尾空格,避免用户输入空字符串或全空格的无效分类
  • 使用SELECT 1代替SELECT *,只需要判断存在性,不需要返回全表数据,提升查询效率
  • 每次查询后调用sqlsrv_free_stmt()释放资源,避免内存泄漏
  • 用exit终止后续代码执行,避免错误后继续执行不必要的逻辑

内容的提问来源于stack exchange,提问作者Legend Whirlwind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:25:28