sqlsrv_query 执行检查数据功能后没有返回任何结果

问题描述

我的公司项目任务是防止重复输入用户注册数据。我希望防止它们重复的数据是电子邮件用户不能使用相同的电子邮件注册应用程序)。检查过程中涉及两个页面(signup.PHP 和insert.PHP)。 Signup.PHP用户在所有 6 个页面上输入信息以注册为公司用户的地方。 Insert.PHP 是将数据插入 sql server 的地方,我已经实现了在将数据插入 sql server 之前进行检查的代码

    //email validation
    $emailvalid="SELECT Email FROM EcomLogin WHERE Email  = '$_POST[email]'";
    $stmt3=sqlsrv_query($conn,$emailvalid);
    if($stmt3){
        header("location:signup.PHP?status=error&message=Error when register with email!");
 exit();
        die(print_r(sqlsrv_errors(),true));
    }

同时在signup.PHP注册表单)中。在表单顶部,我包含了一个 PHP 代码,如果第一页信息与数据库记录重复,在这种情况下是电子邮件,它会阻止网站将用户引导到第二个注册页面

<?PHP 
if(isset($_GET['status']) && $_GET['status'] == 'error'){
echo '<script>toastr.error("Email has already been registered!");history.replaceState(null,"",location.href.split("&")[0]);</script>';}
?>

在 head 部分,我还包含了下面用于 toast 功能的脚本

 <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js" integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw==" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css" integrity="sha512-3pIirOrwegjM6erE5gPSwkUzO+3cTjpnV9lexlNZqvupR64iZBnOOTiiLPb9M36zpMScbmUNIcHUqKD47M719g==" crossorigin="anonymous" />
    <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script>

registration first page

Duplicated email used in sql server database table

在我输入相同的电子邮件地址进行注册后,它会将我带到注册页面的第二页,这是不允许这样做的。如果在第一页上使用重复的电子邮件并将其阻止到注册页面的第二页,则它希望在第一页上出现一条 toastr 消息。

Second page of signup.php after same email address used in first page

我的编码是否有任何部分错误,或者我缺少任何类型的编码来执行 PHP 文件中的阻止功能?如果编码正确,我是否需要创建另一个功能来防止网站将用户直接转到第二页? signup.PHP 将查看另一个 js 文件,该文件首先验证输入字段,然后只执行 insert.PHP

解决方法

您的代码至少存在以下两个问题:

  • 您需要了解 sqlsrv_query() 返回的究竟是什么。如 documentation 中所述,结果是语句资源,或者如果语句无法创建和/或执行,则返回 false。因此,检查 if($stmt3) {...} 表示语句被正确执行,而不是有一行包含指定的电子邮件。
  • 始终使用参数化语句来防止可能出现的 SQL 注入问题。

如果我正确理解您的问题并且您想检查电子邮件是否已经存在,以下方法是可能的解决方案:

  • 使用当前语句并使用 sqlsrv_has_rows() 检查结果集是否包含一行或多行。
  • 更改语句以获取指定电子邮件的行数。

PHP:

<?
...
$sql    = "SELECT Email FROM EcomLogin WHERE Email = ?";
$params = array($_POST[email]);
$stmt   = sqlsrv_query($conn,$sql,$params);
if ($stmt === false) {
    header("location:signup.php?status=error&message=Error when register with email!");
    die(print_r(sqlsrv_errors(),true));
}   
if (sqlsrv_has_rows($stmt)) {
    header("location:signup.php?status=error&message=Error when register with email!");
    die(print_r(sqlsrv_errors(),true));
}
...

...
$sql    = "SELECT COUNT(*) AS EmailCount FROM EcomLogin WHERE Email = ?";
$params = array($_POST[email]);
$stmt   = sqlsrv_query($conn,true));
}   
$count = 0;
while ($row = sqlsrv_fetch_array($stmt,SQLSRV_FETCH_ASSOC)){
    $count = $row["EmailCount"];
}
if ($count >= 1) {
    header("location:signup.php?status=error&message=Error when register with email!");
    die(print_r(sqlsrv_errors(),true));
}
...
?>
,

记住这一点

 $stmt3=sqlsrv_query($conn,$emailvalid);
    if($stmt3){

即使没有这样的电子邮件也可能返回 TRUE,因为 sql 查询是合法的 但不会产生结果或错误。

您可以在这里计算电子邮件:

$emailvalid="SELECT count(Email) as found FROM EcomLogin WHERE Email  = '$_POST[email]'";

获取记录并查看 found 的值

作为防止重复电子邮件的最后一道防线,您可以在电子邮件上方创建一个唯一索引。有了这个数据库本身拒绝重复