Reputation: 65
I was programming my login system, but I got an error that I cannot fix:
Warning: mysqli_stmt_close(): invalid object or resource mysqli_stmt in C:\Users\Acer\Desktop\xampp\htdocs\Login System\includes\signup.inc.php on line 61.
When I save the file and open it, everything works fine until data must be sent to the database. In that moment I get that error and the database is empty.
Here is the code
<?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();
}
Upvotes: 0
Views: 383
Reputation: 44831
TL;DR You call mysqli_stmt_close($stmt);
in a section of code where $stmt
may not be set.
Your primary problem here is that you can't tell what code is running before you get to the mysqli_stmt_close()
. There are two reasons for this: (1) too much code complexity and (2) bad (no) formatting.
The earlier versions of your post included code that wasn't formatted at all (it looks like you have edited it to make it better, but it still has some problems). Formatted properly, your code looks like this:
<?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();
}
In the future, you should use an IDE like PHPStorm, which will help you tremendously with formatting your code and catching obvious errors like this.
For simplicity, let's just look at the structure of your code (...
indicates code I'm leaving out here):
<?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 {
// ...
}
As you can see, $stmt
is only set in one place, inside an else
block. But you try to close it outside that else
block, meaning that $stmt
might never be set before you try to close it.
Move your mysqli_stmt_close($stmt);
inside the else
statement where you set and use $stmt
.
This code is what we call "spaghetti code." I don't say that to be rude; it's just the reality of what you have here. To avoid these kinds of problems in the future:
if... elseif... else
structures. When you have as many elseif
s as you do, something has gone wrong.You really should read through PHP: The Right Way before you write any more code. It will save you a lot of heartburn.
Please note that you have some other problems in this code that I am not addressing here, such as injecting user input directly into URLs in header("Location:...")
without any encoding or filtering. This could be used for, for example, malicious redirects or other nefarious activity. (You also likely have XSS problems on your other pages on your site.)
Upvotes: 2