How can I make this a prepared Statements code? - php

I was under the impression that this was a prepared statement script, but it appears I was wrong. How can I turn this into one? What is a prepared statement?
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "SELECT Status FROM Users WHERE Username = ? AND Password = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $_GET['username'], $_GET['password']);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
if ($result->num_rows > 0) {
// output data of each row or remove while loop if you wish
while($row = $result->fetch_assoc()) {
echo "<b style='color:green'>Found</b>";
}
} else {
echo "0 results";
}
$conn->close();
?>

That's not using prepared statements. This is a basic example with no error/result checking:-
$sql = "SELECT Status FROM Users WHERE Username = ? AND Password = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $_GET['username'], $_GET['password']);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
However you should consider selecting on username only and retrieving the password for comparison. You should also hash your passwords in the database if you're not doing so. Use php's password_hash() and password_verify() for that. The former would help in hashing the password while the latter would be used to verify if the posted password from the html form or original source matches the hashed password
the syntax is
password_hash($_GET['password'], PASSWORD_DEFAULT);
password_verify($_GET['password'], $hashedPasswordFromDatabase);
make sure the column storing the password is varchar(60) at least.

Related

Why can't I get data from SQL row using PHP prepared statements?

Connection is good. I can insert into the database, and check if a row exists by checking if results > 0, but I can not select row data. The $email's being tested are in the database.
Ex 1.
require 'connection/connection.php';
$email = "sample#sample.com";
$sql = "SELECT * FROM users WHERE user_email=?"; // SQL with parameters
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $email);
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$user = $result->fetch_assoc(); // fetch data
echo $user['user_name'];
Ex. 2
$email = "james#james.com";
$sql = "SELECT * FROM users WHERE user_email=?";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_bind_param($stmt, "s", $email);
mysqli_stmt_execute($stmt);
After inserting an echo after every line one by one, this is as far as it gets. If an echo statement is placed after the next line it will not appear.
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result)) {
$_SESSION['active_user_id'] = $row['user_id'];
} else {
header("Location: https://example.com/");
exit();
}
The problem was fixed through cPanel. I had to switch from "mysqli" to "nd_mysqli." This fixed the problem right away.
I found the instructions to do this here https://www.plus2net.com/php_tutorial/mysqli_mysqlnd.php
I hope this helps others with the same problem.

number of rows in database - prepared statements - php

I can't seem to work out how to retrieve number of rows from the database using my query, whenever I run the query It just returns zero even though it's in my database
$username = $_POST['username'];
$hash = password_verify($password, $passwordcheck);
if($stmt = $conn -> prepare("SELECT username, email, password FROM users WHERE (username = ? OR email = ?) AND password = ?"))
{
$stmt -> bind_param("sss", $username, $username, $hash);
$stmt -> execute();
$stmt -> bind_result($checkedUsername, $checkedEmail, $checkedPassword);
$stmt -> fetch();
$numberofrows = $stmt->num_rows;
$stmt -> close();
}
echo '# rows: '.$numberofrows;
Can anyone give me any hints? Can't see to wrap my head around it, thanks.
Btw, the $hash has already been queried prior to this statement.
Posting this as a community wiki:
add $stmt->store_result(); after your execute()
As I assume you have used password_hash() on the password you store in the database. Then you should not be using it in a search criteria. Re-hashing the same string will not generate the same hash using password_hash() as it will use a different SALT each time its run Thats why its the recommended hashing tool.
So you need to do something like this
$username = $_POST['username'];
$stmt = $conn->prepare("SELECT username, email, password
FROM users WHERE (username = ? OR email = ?)")
if($stmt) {
$stmt->bind_param("ss", $username, $username);
$stmt->execute();
// As per #fred-ii- comment
$stmt->store_result();
$stmt->bind_result($checkedUsername, $checkedEmail, $checkedPassword);
$stmt->fetch();
echo '# rows: ' . $stmt->num_rows;
if ( password_verify($_POST['password'], $checkedPassword) ) {
// password is correct
} else {
// password is NOT correct
}
$stmt -> close();
}

Mysqli returns the wrong data

I would like to echo out the values of the column username and tried it like this:
public function username_exists($username) {
$conn = new mysqli($this->servername, $this->username, $this->password, $this->db_name);
$result = mysqli_query($conn, "SELECT username FROM fe_users WHERE username = $username");
while ($row = mysqli_fetch_assoc($result)) {
echo $row["username"];
}
}
When I run this code, for some reason it always returns the string 33, which is also stored in my database but it is definitely not the value of the column username. Why am I getting this output and how can I display the username which is stored in the table fe_users?
You need to quotes around $username
SELECT username FROM fe_users WHERE username = '$username'"
Better use bind and prepare statement. It automatically escape your string and free from sql injection attack
/* prepare statement */
$stmt = $conn->prepare( "SELECT username FROM fe_users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($col1);
/* fetch values */
while ($stmt->fetch()) {
printf("%s %s\n", $col1);
}
/* close statement */
$stmt->close();

Prepared statements and mysqli_query / mysqli_num_rows?

I am trying to find out how to make my code work with prepared statements. I understood the entire process up to where I commented my code. What do I have to do in order to integrate num_rows and the mysqli_query part properly?
function login_check() {
global $connection;
$name = $_POST['name'];
$password = $_POST['password'];
$query = "SELECT id FROM members WHERE name = $name AND password = $password";
$stmt = $connection->prepare($query);
$stmt->bind_param('ss', $name, $password);
$stmt->execute();
$stmt->close();
// $result = mysqli_query($connection, $query);
// $rows = mysqli_num_rows($result);
if($rows > 0){
header('location:../../success.php');
exit;
}
else {
header('location:../../failed.php');
exit;
}
}
What I tried:
$result = mysqli_query($connection, $stmt);
$rows = mysqli_num_rows($result);
Change
$query = "SELECT id FROM members WHERE name = $name AND password = $password";
to
$query = "SELECT `id` FROM `members` WHERE `name` = ? AND `password` = ?";
Adding backticks around table and columns prevents mysql reserved words error.
Remove $stmt->close();
if( $stmt->num_rows > 0 ) {
$stmt->close();
header('location:../../success.php');
exit();
} else {
$stmt->close();
header('location:../../failed.php');
exit();
}
Adding $stmt->close() inside if statement before header is best practice in this case.
Becasue adding it before if statement would result in $stmt->num_rows always returning 0; Adding it after the if statment won't work because exit() would prefent it from executing.
From the documentation:
Closes a prepared statement. mysqli_stmt_close() also deallocates the statement handle. If the current statement has pending or unread results, this function cancels them so that the next query can be executed.

PHP PDO how do i include fetch assoc and numrows

trying to convert all my old mysql_* operations into new and, from what i've heard, improved PDO, but this query wont seem to run successfully, I am trying to select all from the table PEOPLE where the username = $username (which has previously been declared $username = $_SESSION['username'];)
$query = "SELECT * FROM people WHERE username=?";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $username);
$stmt->execute();
$num_rows = $stmt->fetchColumn();
if ($num_rows == 1) {
// ...
}
THE WORKING CODE IS:
$query = "SELECT * FROM people
WHERE username=?";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $username);
$stmt->execute();
$num_rows = $stmt->fetchColumn();
$user = $stmt->fetchObject();
if ($user) {
//do something
}
$stmt->fetchColumn does not fetch the number of rows; in this case it will fetch the first column from the first row of the result set. Since that will not be equal to 1 generally your test will fail.
In this case there is also no real need to count the number of returned rows because you are expecting either one or zero (if the username does not exist). So you can simply do:
$stmt->execute();
$user = $stmt->fetchObject();
if (!$user) {
// not found
}
else {
echo "User $user->username found!";
}
The if(!$user) test works because if there is no row to fetch $user will be false (see the documentation for fetchObject).
$query = "SELECT * FROM people WHERE username = :username";
$stmt = $conn->prepare($query);
$stmt->bindParam(':username', $username);
$stmt->execute();
while ($row = $stmt->fetchObject()) {
// do stuff
}
Use PDOStatement::rowCount as the num_rows and PDOStatement::fetch(PDO::FETCH_ASSOC) as fetch_assoc equivalent.
You want
if ($stmt->num_rows == 1) {
instead.

Categories