how to close connection using prepare statement in php? - php

I am using php to create the user accounts on server database.I have used prepare statement to create user account.I want to know how can i close my sql connection using prepare statement or i don't need to close the connections? Is it done automatically.
Here is my code
public function createUser($name, $email, $password,$file_path,$phone,$address,$profession,$language)
{
$response = array();
// First check if user already existed in db
if (!$this->isUserExists($email)) {
// Generating API key
$api_key = $this->generateApiKey();
// insert query
$stmt = $this->conn->prepare("INSERT INTO users(name, email, password, api_key,profile_pic,phone,address,profession,language,date) values(?, ?, ?, ?, ?, ?, ?, ?,?,now())");
$stmt->bind_param("sssssssss", $name, $email, $password, $api_key,$file_path,$phone,$address,$profession,$language);
$result = $stmt->execute();
$stmt->close();
// Check for successful insertion
if ($result)
{
// User successfully inserted
return USER_CREATED_SUCCESSFULLY;
}
else
{
// Failed to create user
return USER_CREATE_FAILED;
}
}
else
{
// User with same email already existed in the db
return USER_ALREADY_EXISTED;
}
return $response;
}
I am new to php so i don't have any idea about this.

$stmt->close();
is enough .
check this
http://www.w3schools.com/php/php_mysql_prepared_statements.asp

$stmt->close(); // Closes the prepared statement
$this->conn->close(); // Closes the mysql connection

Related

Creating a user directory based off an auto-incremented userID

I am attempting to create a user directory that's name is equal to the user's 'id' which is an auto-incremented column in my database. that will later be used to store text files for the user to access. But, Every time I run this I get an error because $row is null.
For context, This code is run right after a user is inserted into the database.
I've tried checking that $conn is valid and that $username is the correct username. However, when I run createUserDir on an existing user everything works fine.
Code for creating a user (works fine but thought I would show the placement of function call):
function createUser($conn, $email, $username, $pwd) {
$sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?);";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("location: ../register.php?error=stmtfailure");
exit();
}
$hashpwd = password_hash($pwd, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, "sss", $email, $hashpwd, $username);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
createUserDir($conn, $username);
header("location: ../login.php?error=none");
exit();
}
Creates a user directory:
function createUserDir($conn, $username) {
$sql = "SELECT id FROM users WHERE username = ?;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("location: ../register.php?error=stmtfailure");
exit();
}
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt);
$stmtResult = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_assoc($stmtResult);
$uid = $row['id'];
mysqli_stmt_close($stmt);
if(mkdir("../data/users/$uid")) {
die('Failed to create user directory.');
}
}
while creating a record add some text inside of the column, like "NA" so it won't return an error and later update values in last, using $last_id = $conn->insert_id;
might sound silly but might be it will work

Bug in PHP code that causes all the user's passwords to be updated rather than the relevant user

I have a bad issue on our website and require a solution.
So basically, in the code below, we take the user's email as set it as a username in the database and along with it a random password taken from the MOCK_DATA.csv file and stores it in the database.
But it performs a check, so if the username doesn't already exist in the database, then it inserts the username and password. If the username already exists, then just update the password.
Now here is the issue below:
Description of the issue:
After a user has made a purchase, if the username already exists in the database, the password for that user and all other users in the database are updated to that password.
To clarify, it doesn't happen if it's a new user. So if email abc#gmail.com is not in the database, abc#gmail.com and the password 123456 are inserted into the database and none of the other users in the database have their password affected.
However, if I make a purchase with the same email abc#gmail.com again, the password will be updated for that user (let's say 654321), but all other user's passwords in the database will be set to 654321 as well.
Expected result:
The password should only update for that one single user if the username already exists.
Actual Result:
The password updates for all users.
$email_address = $_GET['email'];
$email_address_metis = "xxx#xxx.com.test-google-a.com";
// Get the access code
$csv = array_map('str_getcsv', file('MOCK_DATA.csv'));
// Get random index from array $arrX
$randIndex = array_rand($csv[0]);
// Define variables and initialize with empty values
$username = $password = $confirm_password = "";
$username_err = $password_err = $confirm_password_err = "";
// Processing form data when form is submitted
//if($_SERVER["REQUEST_METHOD"] == "POST"){
// Prepare a select statement
$sql = "SELECT id FROM users WHERE username = ?";
if ($stmt = mysqli_prepare($link, $sql)) {
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "s", $param_username);
// Set parameters
$param_username = $email_address; //trim($_POST["username"]);
// Attempt to execute the prepared statement
if (mysqli_stmt_execute($stmt)) {
/* store result */
mysqli_stmt_store_result($stmt);
if (mysqli_stmt_num_rows($stmt) == 1) {
$username_err = "exists";
}
} else {
$username = $email_address; //trim($_POST["username"]);
}
} else {
echo "Oops! Something went wrong. Please try again later.";
}
// Close statement
mysqli_stmt_close($stmt);
//}
// Output the value for the random index
// Validate password
$password = $csv[0][$randIndex];
if ($username_err !== "exists") {
// Prepare an insert statement
$sql = "INSERT INTO users (username, password) VALUES (?, ?)";
if ($stmt = mysqli_prepare($link, $sql)) {
// Set parameters
$param_password = password_hash($password, PASSWORD_DEFAULT); // Creates a password hash
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "ss", $param_username, $param_password);
// Attempt to execute the prepared statement
if (mysqli_stmt_execute($stmt)) {
// Redirect to login page
// header("location: login.php");
} else {
// echo "Something went wrong. Please try again later.";
}
// Close statement
mysqli_stmt_close($stmt);
}
} else {
// Prepare an update statement
$sql = "UPDATE users SET password = ? WHERE username = ?";
if ($stmt = mysqli_prepare($link, $sql)) {
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "si", $param_password, $param_username);
// Set parameters
$param_password = password_hash($password, PASSWORD_DEFAULT);
$param_username = $username;
// Attempt to execute the prepared statement
if (mysqli_stmt_execute($stmt)) {
// Password updated successfully. Destroy the session, and redirect to login page
session_destroy();
header("location: login.php");
exit();
} else {
echo "Oops! Something went wrong. Please try again later.";
}
// Close statement
mysqli_stmt_close($stmt);
}
}
// Close connection
mysqli_close($link);
So after a long discussion in chat between the OP and I, have come to the conclusion that the $username variable wasn't being populated, which in turn made your query/UPDATE fail because of it, and silently I might add.
Plus, the i in the mysqli_stmt_bind_param() for the UPDATE query was also an issue from the beginning, since you were trying to store a string using an integer format.

Do i need to use $stmt = $conn->prepare for this prepared statement?

The current syntax for my prepared statements is incorrect, where I: (INSERT...?, ?, ?)
I have tried to copy syntax from different examples but it seems the more I try the more I break my login system.
I have somewhat conflicting examples and am not sure which syntax is the correct one to use. Do I need to use $stmt = $conn->prepare before INSERT?
// create preprepared statement
$sql = "INSERT INTO `user` (username, password, email) VALUES (?, ?, ?)";
// check if sql statement is correct
if ($stmt = mysqli_prepare($connection, $sql)) {
// Add the variables to the stmt
mysqli_stmt_bind_param($stmt, "sss", $param_username, $param_hashed_password, $param_email);
$param_username = $username;
$param_password = $hashed_password;
$param_email = $email;
// Attempt to execute the stmt
if(mysqli_stmt_execute($stmt)) {
// If statement executed
$_SESSION["username"] = $username;
header("location: login.php");
At the moment it's not inserting any values into my db and user registration is failing.
EDIT:
$password = $_POST['password'];
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
It has just occurred to me that this might be incorrect usage of password_hash?
Do i need to use "$stmt = $conn->prepare" for this prepared statement? - in short, No! You must however use the prepare method to actually generate the prepared statement, it MUST be done before actually attempting to do the INSERT and it is wise to assign that to a variable so that you can fork the program logic dependant upon success/failure.
My preference is to do as below - use a try/catch block and use the return values or variables at various stages to determine whether to throw meaningful(?) exceptions to help debug - so as example you could do this
/*
assumed that $username,$password & $email
are all defined and available at ths stage.
also assumed that `session_start()` has
been called and that no html output occurs
before this point ( unless using output buffering )
*/
try{
# example
$sql = "INSERT INTO `user` ( `username`, `password`, `email` ) VALUES (?, ?, ?)";
$stmt = $connection->prepare( $sql );
if( $stmt ){
/* if there were no problems continue with the database operations */
$stmt->bind_param('sss', $username, $hash, $email );
/* not sure how the hash was generated so just put this in to be sure... */
$hash = password_hash( $password, PASSWORD_BCRYPT );
$result = $stmt->execute();
$stmt->free_result();
$stmt->close();
if( $result ){
$_SESSION['username'] = $username;
exit( header( 'Location: login.php' ) );
} else {
throw new Exception('Bogus! There was some sort of problem...');
}
} else {
throw new Exception('Failed to prepare sql query');
}
}catch( Exception $e ){
exit( $e->getMessage() );
}

mysqli_stmt::bind_result(): error [duplicate]

This question already has answers here:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
(2 answers)
Closed 1 year ago.
hi i've been using php for a while now but i'm still quiet new to a few things one of which is the bind_result(). So i'm creating a login system on a project but i keep getting the error:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
i know this is to do with the fact that i'm selecting all the columns, what i want to know do i have to bind all of the columns or is their an easier way?
my code in function.php
public function getUserByEmailAndPassword($email, $password) {
$sql = "SELECT * FROM users WHERE email = ?"; // SQL Statement
$stmt = $this->conn->prepare($sql); // Prepare the SQL Statement
$stmt->bind_param('s', $email); // Bind the placeholder with the correct data type from the SQL Statement
$stmt->execute(); // Execute the prepared statement
$stmt->store_result(); // Store the prepared statement for later checking
// Check to make sure if any data is returned
if($stmt->num_rows) {
// Create and append variables
$user = $stmt->bind_result($email);
// Create a while loop
while($stmt->fetch()) {
// verifying user password
$salt = $user['salt'];
$encrypted_password = $user['encrypted_password'];
$hash = $this->checkhashSSHA($salt, $password);
// check for password equality
if ($encrypted_password == $hash) {
// user authentication details are correct
$stmt->close();
return $user;
}else {
}
}
return NULL;
}
}
You can try this code. But as your query is not clear please encrypt your password and then check in if condition
function getUserByEmailAndPassword($email) {
$stmt = $conn->prepare('SELECT
email,
password
FROM users
WHERE email = ?
');
$stmt->bind_param('s',$email);
$stmt->execute();
$stmt->store_result();
while($stmt->fetch()){
$row = array('email'=>$email,'password'=>$password);
}
$stmt->close();
if(!empty($row)){
return $row;
} else {
return "";
}
}
$userDetails = getUserByEmailAndPassword($email);
//Encrypt your password here
if($userDetails['password'] == $encryped_password){
//do_something
}

New to bind_param, what's wrong with this code?

// Insert the new user into the database
// This WORKS, and was copied from an example
if ($insert_stmt = $mysqli->prepare("INSERT INTO members (username, email, password, salt) VALUES (?, ?, ?, ?)")) {
$insert_stmt->bind_param('ssss', $username, $email, $password, $random_salt);
// Execute the prepared query.
if (! $insert_stmt->execute()) {
header('Location: ../error.php?err=Registration failure: MEMBER. Please contact the developer.');
}
$insert_stmt->close();
// If user inserted, add place with user as owner
// This DOESN'T work, and was added by me
//$ownerid = $mysqli->lastInsertId();
$placename = $_POST['placename'];
$placename = mysqli_real_escape_string($mysqli, $placename);
$location = $_POST['autocomplete'];
$location = mysqli_real_escape_string($mysqli, $location);
if ($place_stmt = $mysqli->prepare("INSERT INTO places (member_owner, location, name) VALUES (?, ?, ?)")) {
$place_stmt->bind_param('iss', 1, $location, $placename);
if (! $place_stmt->execute()) {
header('Location: ../error.php?err=Registration failure: PLACE. Please contact the developer.');
}
}
$place_stmt->close();
}
header('Location: ./register_success.php');
I can confirm that the 2 variables $location and $placename are successfully retrieved. The result I get from running this code is that the members table is successfully updated, but the places table is not and the script dumps me into a blank HTML.
I figured out that bind_param doesn't like to accept hard-coded values. I was trying to "test" my code by inserting a value of 1 into a column before I messed around with trying to get the last inserted ID. The error reporting suggested by Fred really helped (as did other suggestions, as you can see I've implemented).
The altered code:
// Insert the new user into the database
if ($insert_stmt = $mysqli->prepare("INSERT INTO members (username, email, password, salt) VALUES (?, ?, ?, ?)")) {
$insert_stmt->bind_param('ssss', $username, $email, $password, $random_salt);
// Execute the prepared query.
if (! $insert_stmt->execute()) {
header('Location: ./error.php?err=Registration failure: MEMBER. Please contact the developer.');
exit;
}
$insert_stmt->close();
// If user inserted, add place with user as owner
$ownerid = $mysqli->insert_id;
if ($place_stmt = $mysqli->prepare("INSERT INTO places (member_owner, location, name) VALUES (?, ?, ?)")) {
$place_stmt->bind_param('iss', $ownerid, $location, $placename);
if (! $place_stmt->execute()) {
header('Location: ./error.php?err=Registration failure: PLACE. Please contact the developer.');
exit;
}
}
$place_stmt->close();
header('Location: ./register_success.php');
}
Thanks for all the help!

Categories