如何修复mysqli_stmt_close无效对象错误?

时间:2018-12-29 16:22:42

标签: php

我正在对登录系统进行编程,但是遇到了无法修复的错误:

  

警告:mysqli_stmt_close():C:\ Users \ Acer \ Desktop \ xampp \ htdocs \ Login System \ includes \ signup.inc.php中无效的对象或资源mysqli_stmt。

当我保存并打开文件时,一切正常,直到必须将数据发送到数据库为止。在那一刻,我收到该错误,并且数据库为空。

这是代码

<?php
if (isset($_POST['signup-submit'])) {
    require 'dbh.inc.php';

    $username = $_POST['uid'];
    $email = $_POST['mail'];
    $password = $_POST['pwd'];
    $passwordrepeat = $_POST['pwd-repeat'];

    if (empty($username) || empty($email) || empty($password) || empty($passwordrepeat)) {
        header("Location: ../signup.php?error=emptyfields&uid=".$username."&mail=".$email);
        exit();
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL) && !preg_match("/^[a-zA-Z0-9]*$/", $username)) {
        header("Location: ../signup.php?error=invalidmailuid");
        exit();
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        header("Location: ../signup.php?error=invalidmail&uid=".$username);
        exit();
    } elseif (!preg_match("/^[a-zA-Z0-9]*$/", $username)) {
        header("Location: ../signup.php?error=invaliduid&mail=".$email);
        exit();
    } elseif ($password !== $passwordrepeat) {
        header("Location: ../signup.php?error=passcheck&uid=".$username."&mail=".$email);
        exit();
    } else {
        $sql = "SELECT uidUsers FROM users WHERE uidUsers=?";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt, $sql)) {
            header("Location: ../signup.php?error=sqlerror");
            exit();
        }
        else {
        mysqli_stmt_bind_param($stmt, "s", $username);
        mysqli_stmt_execute($stmt);
        mysqli_stmt_store_result($stmt);
        $resultCheck = mysqli_stmt_num_rows($stmt);  
        if ($resultCheck > 0){
        header("Location: ../signup.php?error=usertaken&mail=".$email);
        exit();
        }
        else {
        $sql = "INSERT INTO users (uidUsers, mailUsers, pwdUsers) VALUES (?, ?, ?)";
        $stmt = mysqli_stmt_init($conn);
         if (!mysqli_stmt_prepare($stmt, $sql)) {


         }
         else {
            $hashedPwd = password_hash($password, PASSWORD_DEFAULT);

            mysqli_stmt_bind_param($stmt, "sss", $username, $email, $hashedPwd);
            mysqli_stmt_execute($stmt);
            header("Location: ../signup.php?signup=success");
            exit();
            }
        }
      }


    }
    mysqli_stmt_close($stmt);
    mysqli_close($conn);
}
else {
header("Location: ../signup.php");
exit();
}

1 个答案:

答案 0 :(得分:1)

TL; DR 您在可能未设置mysqli_stmt_close($stmt);的代码段中调用$stmt

问题

您的主要问题是,在进入mysqli_stmt_close()之前,您无法知道正在运行什么代码。造成这种情况的原因有两个:(1)代码过于复杂和(2)格式错误(没有)。

修复格式

您的帖子的早期版本中的代码根本没有格式化(看起来您已经对其进行了编辑以使其更好,但仍然存在一些问题)。格式正确,您的代码如下所示:

<?php
if (isset($_POST['signup-submit'])) {
    require 'dbh.inc.php';

    $username = $_POST['uid'];
    $email = $_POST['mail'];
    $password = $_POST['pwd'];
    $passwordrepeat = $_POST['pwd-repeat'];

    if (empty($username) || empty($email) || empty($password) || empty($passwordrepeat)) {
        header("Location: ../signup.php?error=emptyfields&uid=" . $username . "&mail=" . $email);
        exit();
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL) && !preg_match("/^[a-zA-Z0-9]*$/", $username)) {
        header("Location: ../signup.php?error=invalidmailuid");
        exit();
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        header("Location: ../signup.php?error=invalidmail&uid=" . $username);
        exit();
    } elseif (!preg_match("/^[a-zA-Z0-9]*$/", $username)) {
        header("Location: ../signup.php?error=invaliduid&mail=" . $email);
        exit();
    } elseif ($password !== $passwordrepeat) {
        header("Location: ../signup.php?error=passcheck&uid=" . $username . "&mail=" . $email);
        exit();
    } else {
        $sql = "SELECT uidUsers FROM users WHERE uidUsers=?";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt, $sql)) {
            header("Location: ../signup.php?error=sqlerror");
            exit();
        } else {
            mysqli_stmt_bind_param($stmt, "s", $username);
            mysqli_stmt_execute($stmt);
            mysqli_stmt_store_result($stmt);
            $resultCheck = mysqli_stmt_num_rows($stmt);
            if ($resultCheck > 0) {
                header("Location: ../signup.php?error=usertaken&mail=" . $email);
                exit();
            } else {
                $sql = "INSERT INTO users (uidUsers, mailUsers, pwdUsers) VALUES (?, ?, ?)";
                $stmt = mysqli_stmt_init($conn);
                if (!mysqli_stmt_prepare($stmt, $sql)) {


                } else {
                    $hashedPwd = password_hash($password, PASSWORD_DEFAULT);

                    mysqli_stmt_bind_param($stmt, "sss", $username, $email, $hashedPwd);
                    mysqli_stmt_execute($stmt);
                    header("Location: ../signup.php?signup=success");
                    exit();
                }
            }
        }
    }
    mysqli_stmt_close($stmt);
    mysqli_close($conn);
} else {
    header("Location: ../signup.php");
    exit();
}

将来,您应该使用像PHPStorm这样的IDE,它将极大地帮助您格式化代码并捕获诸如此类的明显错误。

发现错误

为简单起见,我们只看一下代码的结构(...表示我在这里省略的代码):

<?php
if (isset($_POST['signup-submit'])) {
    require 'dbh.inc.php';

    $username = $_POST['uid'];
    $email = $_POST['mail'];
    $password = $_POST['pwd'];
    $passwordrepeat = $_POST['pwd-repeat'];

    if (empty($username) || empty($email) || empty($password) || empty($passwordrepeat)) {
        // ...
    } 
    // ... long series of elseif statements here...
    else {
        $sql = "SELECT uidUsers FROM users WHERE uidUsers=?";
        $stmt = mysqli_stmt_init($conn);
        // ...
    }
    mysqli_stmt_close($stmt);
    mysqli_close($conn);
} else {
    // ...
}

如您所见,$stmt仅设置在else块内的一个位置。但是,您尝试在else块的 outside 外部关闭它,这意味着$stmt可能永远不会在尝试关闭它之前设置。

立即修复

mysqli_stmt_close($stmt);移至设置和使用else的{​​{1}}语句中。

实际修复

此代码就是我们所说的“意大利面条代码”。我并不是说这很无礼。这只是您在这里拥有的现实。为避免将来出现此类问题:

  • 将代码分成函数或类。
  • 避免使用复杂的深$stmt结构。当您有if... elseif... else个字元时,就出问题了。
  • 请学习如何正确设置代码格式。
  • 使用IDE。

在编写更多代码之前,您确实应该通读PHP: The Right Way。它将为您节省很多胃灼热的感觉。

请注意,您在此代码中还有其他一些我没有解决的问题,例如将用户输入直接插入elseif中的URL中,而没有进行任何编码或过滤。例如,这可用于恶意重定向或其他恶意活动。 (您网站上其他页面上也可能遇到XSS问题。)