I have a signup form on my website and the following code should run whenever a new user signs up:
$sql = "SELECT * FROM users WHERE uidUsers=?;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt);
$resultCheck = mysqli_stmt_num_rows($stmt);
if ($resultCheck > 0) {
header("Location: ../signup.php?error=usertaken");
exit();
}
else {
$hashedPwd = password_hash(PASSWORD_DEFAULT, $password);
$sql = "INSERT INTO users (`uidUsers`, `pwdUsers`, `phraseUsers`) VALUES(?,
?, ?)";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "sss", $username, $hashedPwd,
$securityphrase);
mysqli_stmt_execute($stmt);
header("Location: ../login.php?signup=success");
exit();
}
The !mysqli_stmt_prepare error handler is triggered when it shouldn't be given the database circumstance, as well as the correct INSERT statement. Therefore I don't understand why it's triggered and I'm asking why?
There is a similar question here on Stack Overflow
Thank you for your help, the problems where the password_hash order, it should be like this password_hash($var, PASSWORD_DEFAULT);. The second mistake I made was not including my $sql statements in the mysqli_stmt_prepare, it should be like this !mysqli_stmt_prepare($stmt, $sql).
Related
This question already has an answer here:
Should I manually check for errors when calling "mysqli_stmt_prepare"?
(1 answer)
Closed 1 year ago.
I'm trying to make a registeration form using php and sql but i keep getting "mysqli_stmt object is not fully initialized" as an error message.
Registration.php file:
$sql = "INSERT INTO user_table ('user_name', 'user_email', 'user_password') VALUES (?, ?, ?)";
$stmt = mysqli_stmt_init($conn);
if (mysqli_stmt_prepare($stmt, $sql)){
header("location: ../signup.php?error=sqlerror");
exit();
} else {
//hashing password
$hashedPass = password_hash($password, PASSWORD_DEFAULT);
//inserting hashed password.
mysqli_stmt_bind_param($stmt, "sss", $username, $email, $hashedPass);
mysqli_stmt_execute($stmt);
header("location: ../signup.php?success=registered");
exit();
}
I think the problem is in this part (in the line number 8).
If we remove your if/else check and run everything, with the mysqli_stmt_prepare after the mysqli_stmt_init we get what we expect.
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
So the logic on your if seems like it needs a ! (meaning false). Try this alteration to your code block:
$sql = 'INSERT INTO user_table (user_name, user_email, user_password) VALUES (?, ?, ?)';
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("location: ../signup.php?error=sqlerror");
exit();
} else {
//hashing password
$hashedPass = password_hash($password, PASSWORD_DEFAULT);
//inserting hashed password.
mysqli_stmt_bind_param($stmt, 'sss', $username, $email, $hashedPass);
mysqli_stmt_execute($stmt);
header("location: ../signup.php?success=registered");
exit();
}
The above code worked in my test.
Having this code:
$sql = "SELECT * FROM users WHERE user_login=?;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
die(mysqli_error($conn));
} else {
mysqli_stmt_bind_param($stmt, 's', $login);
mysqli_stmt_execute($stmt);
mysqli_store_result($conn);
$resultCheck = mysqli_stmt_num_rows($stmt);
//err == login name is already taken
if ($resultCheck > 0) {
die("login is taken");
} else {
$sql = "INSERT INTO users(user_login, user_email, user_pwd) VALUES (?, ?, ?);";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
die(mysqli_error($conn));
} else {
$hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, 'sss', $login, $email, $hashedPwd);
mysqli_stmt_execute($stmt);
}
// insert_usertodb($conn, $login, $email, $pwd);
}
}
works fine (`e.g. the part where is user inserted does not gives any mysqli error), however, if I tried to use a function, where the user is inserted:
function insert_usertodb($conn, $user_login, $user_email, $user_pwd)
{
$sql = "INSERT INTO users(user_login, user_email, user_pwd) VALUES (?, ?, ?);";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) { // <-- this is where the error happens
// err_signup('sqlierror', '', '');
die('sqlierror: ' . mysqli_error($conn));
} else {
//hash password
$hashedPwd = password_hash($user_pwd, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, 'sss', $user_login, $user_email, $hashedPwd);
mysqli_stmt_execute($stmt);
// header("Location: ../signup.php?signup=success");
}
}
And use it instead of the part, where the user is inserted (after else branch -> the function is commented at the end), the mysqli generates error:
Commands out of sync; you can't run this command now
Is there any reason, why the function with identical code (like literally copied the part (where is the insertion) and just change the variables name to be the argument that function) generates the out-of-sync error? and the code without the func doesn't?
This is because you used a wrong function here mysqli_store_result($conn);. You should have used mysqli_stmt_store_result($stmt); instead. This means that your code is not working as you wanted it to and the check for existence is broken. This is why it is a terrible idea to use mysqli_stmt_num_rows().
The reason why it works when it is not in the function is that you call the destructor on the $stmt object when you assign it a different value in $stmt = mysqli_stmt_init($conn);. When a destructor is called it will fetch all results in the background to "clean" the wire.
If it is not too late consider using PDO instead. It is simpler and you won't be making such mistakes so often. The code which you have written with mysqli is too verbose. You don't need most of it. This would be so much easier with PDO.
$username = $_POST['uid'];
$email = $_POST['mail'];
$password = $_POST['pwd'];
$passwordRepeat = $_POST['pwd-repeat'];
$date = $_POST['date2'];
$stream = $_POST['relationship'];
$sql1 = "INSERT INTO users (uidUsers, emailUsers, pwdUsers, relationship) VALUES (?, ?, ?, ?);";
$sql2 = "INSERT INTO Family1 (username, application_filed, relationship) VALUES (?, ?, ?);";
$sql3 = "INSERT INTO Family2 (username, application_filed, relationship) VALUES (?, ?, ?);";
mysqli_query($sql1, $conn);
mysqli_query($sql2, $conn);
mysqli_query($sql3, $conn);
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql2)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "sss", $username, $date, $stream);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result))
($username==$_SESSION['uid'] and $stream =='nursing');
mysqli_stmt_execute($stmt);
}
if (!mysqli_stmt_prepare($stmt, $sql3)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "sss", $username, $date, $stream);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result))
($username==$_SESSION['uid'] and $stream =='doctoral');
mysqli_stmt_execute($stmt);
}
if (!mysqli_stmt_prepare($stmt, $sql1)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
if (!mysqli_stmt_prepare($stmt, $sql1)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
$hashedPwd = password_hash($password, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, "ssss", $username, $email, hashedPwd,$stream);
mysqli_stmt_execute($stmt);
header("Location: ../signup.php?signup=success");
exit();
/////////////New Code////////////////
$username = $_POST['uid'];
$email = $_POST['mail'];
$password = $_POST['pwd'];
$passwordRepeat = $_POST['pwd-repeat'];
$date = $_POST['date2'];
$stream = $_POST['relationship'];
$sql1 = "INSERT INTO users (uidUsers, emailUsers, pwdUsers, relationship) VALUES (?, ?, ?, ?);";
$sql2 = "INSERT INTO Family1 (username, application_filed, relationship) VALUES (?, ?, ?);";
$sql3 = "INSERT INTO Family2 (username, application_filed, relationship) VALUES (?, ?, ?);";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql2)) {
header("Location: ../signup.php?error=sqlerror");
exit();
} else if ($username==$_SESSION['uid'] && $stream =='nursing') {
mysqli_stmt_bind_param($stmt, "sss", $username, $date, $stream);
mysqli_stmt_execute($stmt);
}
if (!mysqli_stmt_prepare($stmt, $sql3)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else if ($username==$_SESSION['uid'] && $stream =='doctoral') {
mysqli_stmt_bind_param($stmt, "sss", $username, $date, $stream);
mysqli_stmt_execute($stmt);
}
if (!mysqli_stmt_prepare($stmt, $sql1)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
$hashedPwd = password_hash($password, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, "ssss", $username, $email, $hashedPwd, $stream);
mysqli_stmt_execute($stmt);
header("Location: ../signup.php?signup=success");
exit();
}
I was wondering if someone could point me in the right direction. I have this code. They idea I had behind it is to insert values into different tables depending on variables being passed.
So when user fills out a form and selects $stream="nursing" I want results to go to table 'users' and 'Family1', but not 'Family2' table. and if user selects $stream='doctoral' results should go to table 'users' and 'Family2', and not go to 'Family1'
But with my query I get results go to both table and also users table. And there is no restriction to what users selects, variable $stream being passed no matter what it is.
Is this the wrong way to go here? Did I completely mess up the logic?
For one thing, the mysqli_query() calls at the top will try to run the queries and will fail, since it has no understanding of the ? placeholders and you have the $conn and $sqlX variables the wrong way around.
But aside from that, let me fix the indentation for you so you can see what's actually happening for one of your statements:
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql2)) {
header("Location: ../signup.php?error=sqlerror");
exit();
} else {
mysqli_stmt_bind_param($stmt, "sss", $username, $date, $stream);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result))
($username==$_SESSION['uid'] and $stream =='nursing');
mysqli_stmt_execute($stmt);
}
Do you see what's happening here?
$sql2 is an INSERT query. If you were able to prepare that statement you try to get the result before the query is even executed. If you manage to retrieve a row of data from that result (which you can't since an INSERT query does not return any records), you then do a check on $username and $stream that has no effect. The call to execute the prepared statement is executed regardless of whether or not you managed to get anything from $result.
All your statements have the same problems, so I'll only fix this one.
Here's what I changed:
The whole $result step seemed unnecessary, so I removed it.
I replaced and with && because of my personal preference. There was once a reason why it became my preference, but I forget. It's mostly for consistency between programming languages, since many languages use && and only a few use and.
Since there's no point in binding params to a statement you're not planning to execute, I moved that into the if-statement.
Since I now ended up with an else { if { ... } } construction, I simplified that down to an else if { ... } for cleaner code.
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql2)) {
header("Location: ../signup.php?error=sqlerror");
exit();
} else if ($username==$_SESSION['uid'] && $stream =='nursing') {
mysqli_stmt_bind_param($stmt, "sss", $username, $date, $stream);
mysqli_stmt_execute($stmt);
}
Now, the query $sql2 is only executed if the $username matches the current uid from the session and the user selected the nursing stream.
When I tried to execute it, it says:
Uncaught Error: Call to undefined function mysqli_stmnt_init()
else{
$sql = "SELECT uidUsers FROM user WHERE uidUsers=?";
$stmt = mysqli_stmnt_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, emailUsers, pwdUsers) VALUES (?, ?, ?)";
$stmt = mysqli_stmnt_init($conn);
if (!mysqli_stmt_prepare($stmt,$sql)){
header("Location: ../signup.php?error=sqlerror");
exit();
}
As mentioned in the comments above. You have a typo, the actual function call should be mysqli_stmt_init() whereas you have mysqli_stmnt_init().
What i want to do is to check if the email & username are already inside on my database, then if it is already inside the database then i want to echo out the username, how to fix this? thanks
$sql = "SELECT * FROM user WHERE uidUser=? OR emailUser=?";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../signup.php?error=sqlerror");
exit();
}
else {
mysqli_stmt_bind_param($stmt, "ss", $username, $email);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$resultCheck = mysqli_stmt_num_rows($stmt);
if ($resultCheck > 0) {
while ($row=mysqli_stmt_fetch($stmt)) {
echo "Name: ".$row['uidUser'];
}
}
}