Mysqli Prepare is not working inside another prepared statement - php

I am trying to run a prepared statement inside a prepared statement but got no success. Here is my code:
if ($stmt = $mysqli->prepare("SELECT author_id FROM posts")) {
$stmt->execute();
$stmt->bind_result($author_id);
while ($stmt->fetch()) {
if ($stmt2 = $mysqli->prepare("SELECT username FROM users WHERE id=? LIMIT 1")) {
$stmt2->bind_param("s", $author_id);
$stmt2->execute();
$stmt2->bind_result($username);
$stmt2->fetch();
$stmt2->close();
//showing username
echo $username;
}
}
$stmt->close();
}
I am getting author id from a table and then from author id I'm trying to get author's name from another table.
Can you please tell me any way to do this or any modification in this script can get it done.

Sometimes PHP section of this site makes my eyes aching. Not only question lacks very basic knowledge in every aspect of programming, but also answers promote terrible practices.
You have to report errors to make yourself aware of the certain reason. Either usual way, via $conn->error or by setting mysqli in exception mode.
After reading the error message, you can google for a solution - store_result()
For such a dataset, NO loop needed ever, as you have to use JOIN instead:
And so whole code become
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$sql = "SELECT username FROM posts p, users u WHERE u.id=author_id";
$res = $mysqli->query($sql);
while ($row = mysqli_fetch_row()) {
echo $row[0];
}

Use another mysqli object for inner loop.
$mysqli = new mysqli(host, user, password, dbname);
$mysqli2 = new mysqli(host, user, password, dbname);
if ($stmt = $mysqli->prepare("SELECT author_id FROM posts")) {
$stmt->execute();
$stmt->bind_result($author_id);
while ($stmt->fetch()) {
if ($stmt2 = $mysqli2->prepare("SELECT username FROM users WHERE id=? LIMIT 1")) {
$stmt2->bind_param("s", $author_id);
$stmt2->execute();
$stmt2->bind_result($username);
$stmt2->fetch();
$stmt2->close();
//showing username
echo $username;
}
}
$stmt->close();

Related

PHP: Insert into MySQL database and check if already existing - with binding parameters

I am trying to insert test data into a MySQL database using the below lines which works fine so far.
1) How can I check whether the email already exists in the database and if, echo a message? I saw references here to the use of WHERE EXISTS or mysqli_num_rows but I am not sure which and how to apply here - in combination with binding parameters.
2) I came across unset($username, $password, $database); to make this query more secure. Is that something that is needed / useful here and if, where should I put it ?
My PHP:
$conn = new mysqli($host, $username, $password, $database);
if($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$stmt = $conn->prepare("INSERT INTO cust (email, pw) VALUES (?, ?)");
$stmt->bind_param("ss", $email, $hashPw);
$email = "me#mail.com";
$pw = "testpw12345";
$hashPw = password_hash($pw, PASSWORD_DEFAULT);
$stmt->execute();
echo "Success";
$stmt->close();
$conn->close();
An alternative to the solution proposed already.
$stmt = $conn->prepare("SELECT COUNT(1) FROM cust WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$emailExists = $stmt->get_result()->fetch_row()[0];
if ($emailExists) {
echo "This email address is already in use";
} else {
// continue with insert code
}
This approach does not require you to close the statement. Once you execute get_result the statement data is fetched in full.
This solution also has a potential performance benefit. If your table contains many columns with many data, then fetching that data just to check if a record exists is a waste of CPU. Simply fetch COUNT(1) and check the single column of the single returned record. If it is 0, the value is falsish, if it is more than your if statement will evaluate to true and a message will be displayed. I would also strongly recommend to structure your code in such a way that you rarely have to use exit.
To check if the email already exists in the database, just try to select a row with it in:
$stmt = $conn->prepare("SELECT * FROM cust WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
echo "This email address is already in use";
exit;
}
$stmt->close();
// continue with insert code
In terms of your other questions, I don't see any reason to unset variables, and using prepared queries and password_hash gives you about as good protection as you can get.

Login PDO script gives an error of `Call to a member function blind_param() on boolean`

I have this login code while I tried exactly what the tutorial said, yet it gave me this error :
Call to a member function blind_param() on boolean
The code goes as:
<?php
include ('db.php');
$sql = "SELECT id FROM users WHERE email = ?"."AND password = ?";
$stmt = $conn->prepare($sql);
$stmt->blind_param('ss',$_POST['email'],$_POST['password']);
$stmt->execute();
$stmt->blind_result($id);
if($stmt->fetch())
{
echo 'loggin in';
} else {
echo 'try again';
}
Any Help is Greatly Appreciated..
$stmt -> bindParam(1,$_POST['email']);
$stmt -> bindParam(2,$_POST['password']);
For a prepared statement using question mark placeholders, this will be the 1-indexed position of the parameter.
see:http://php.net/manual/en/pdostatement.bindparam.php
You query missing a space between ? and AND :
$sql = "SELECT id FROM users WHERE email = ? "."AND password = ?";
So, $conn->prepare($sql); fails and $stmt is false.
You should ever test the results of the functions :
$stmt = $conn->prepare($sql);
if (!$stmt) { /* handle error */ }
else {
$stmt->bind_param(...);
}
NB: PDO uses bindParam(), MySQLi uses bind_param() and bind_result().

Update sql using bind param

I have a sql statement to update confirm code and code in the database. I'm using bind param to bind the variables. It worked fine for my select and insert sql statements. However, it keeps giving me this error:
Fatal error: Uncaught Error: Call to a member function bind_param() on boolean
when I tried to execute the update query. I tried to search on every forums possible but found no answers and I hope someone could maybe spot my mistake. I'm having issues with $query1. Both code and confirmcode are varchar and not integer.
$username = $_GET['username'];
$code = $_GET['code'];
$confirmcode = "1";
$updatecode ="0";
$query=$con->prepare("SELECT username, code FROM customer_detail WHERE username ='$username'");
$query->execute();
$query->bind_result($checkusername, $checkcode);
$query->fetch();
$query1=$con->prepare("UPDATE customer_detail SET code=?, confirmcode=? WHERE username = ?"); //error
$query1->bind_param('sss',$username, $updatecode, $confirmcode); //error
$query1->execute();
The problem is that MySQLi can't run multiple queries at once, because it uses ubuffered queries. You'll need to close the first statement before you can run another. Add the following line after $query->fetch();.
$query->close();
This being said, your first query isn't guarded against SQL injection, because you use the variable directly in the query. Adding proper placeholders for your query, the final code would look like this
$query = $con->prepare("SELECT username, code FROM customer_detail WHERE username =?");
$query->bind_param('s', $username);
$query->execute();
$query->bind_result($checkusername, $checkcode);
$query->fetch();
$query->close();
$query1 = $con->prepare("UPDATE customer_detail SET code=?, confirmcode=? WHERE username = ?");
$query1->bind_param('sss',$username, $updatecode, $confirmcode);
$query1->execute();
$query1->close();
Try below code. Basically, you need to bind the params in the same order in which the placeholders (?) appear in the sql.
$query=$con->prepare("SELECT username, code FROM customer_detail WHERE username = ?");
$query->bind_param('s', $username);
$query->execute();
$query->bind_result($checkusername, $checkcode);
$query->fetch();
$query1=$con->prepare("UPDATE customer_detail SET code=?, confirmcode=? WHERE username = ?");
$query1->bind_param('sss', $updatecode, $confirmcode, $username);
$query1->execute();
Have you tried tis?
$query1->bind_param('iis', $updatecode, $confirmcode, $username);

Use prepared statements to check user override credentials, user override rights, and delete MySQL table Record

I am trying to build an override feature so users can manually remove a MySQL table row if they have the correct rights to do so. The user is prompted to input the same credentials used for program login as well as the uniqueID for the row that needs to be removed. Upon hitting the 'Submit' function, I run a series of if statements/ MySQL SELECT statements to check credentials, user rights and finally row Deletion with the result output as an alert.
However, my alert shows up blank and the row is not removed so I know there is a problem with my if statements. Upon testing, I believe the problem is when I try to use the previous query's results to run the next if statement logic.
How do I properly determine if the MySQL query returned a row using prepared statements?
All help is appreciated! Thank you!
My CODE:
if ((isset($_POST['overrideUsername'])) and (isset($_POST['overridePassword'])) and (isset($_POST['overrideUniqueID']))) {
$overridePasswordInput = $_POST['overridePassword'];
$overrideUsername = $_POST['overrideUsername'];
$overridePassword = ENCODE(($overridePasswordInput).(ENCRYPTION_SEED));
$roleID = '154';
$overrideUniqueID = $_POST['overrideUniqueID'];
//connect to the database
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if(mysqli_connect_errno() ) {
printf('Could not connect: ' . mysqli_connect_error());
exit();
}
$conn->select_db($dbname);
if(! $conn->select_db($dbname) ) {
echo 'Could not select database. '.'<BR>';
}
$sql1 = "SELECT users.id FROM users WHERE (users.login = ?) AND (users.password = ?)";
$stmt1 = $conn->prepare($sql1);
$stmt1->bind_param('ss', $overrideUsername, $overridePassword);
$stmt1->execute();
$stmt1->bind_result($userID);
//$result1 = $stmt1->get_result();
if ($stmt1->fetch()) {
$sql2 = "SELECT * FROM rolestousers WHERE (rolestousers.userid = ?) AND (rolestousers.roleid = ?)";
$stmt2 = $conn->prepare($sql2);
$stmt2->bind_param('ss', $userID, $roleID);
$stmt2->execute();
$stmt2->store_result();
if ($stmt2->fetch()) {
$sql3 = "DELETE * FROM locator_time_track_out WHERE locator_time_track_out.uniqueid = ?";
$stmt3 = $conn->prepare($sql2);
$stmt3->bind_param('s', $overrideUniqueID);
$stmt3->execute();
$stmt3->store_result();
if ($stmt3->fetch()) {
echo 'Override Successful! Please scan the unit again to close it out.';
} else {
echo 'Could Not Delete Record from the table.';
}//End $sql3 if.
} else {
echo 'User does not have override permission. Please contact the IT Department.';
}//End $sql2 if.
} else {
echo 'Your login information is incorrect. Please try again. If the issue persists, contact the IT Department.';
}//End $sql1 if.
//Free the result variable.
$stmt1->free();
$stmt2->free();
$stmt3->free();
$stmt1->close();
//Close the Database connection.
$conn->close();
}//End If statement
NOTE: I am definitely sure my DB connection information is correct. The issue resides after I connect into the database. I have also tested the code using only the first if statement and get the blank alert so I'm not making it past the first if statement.
EDIT:: My php Script was definitely failing, but even earlier than expected, at the following code:
$overridePassword = ENCODE(($overridePasswordInput).(ENCRYPTION_SEED));
So my issue is that I need to properly compare the password and encryption seed information. However, the previous programmer used the following line to do the same process (which is obviously unsafe):
$querystatement = "SELECT id, firstname, lastname, email, phone, department, employeenumber, admin, usertype FROM users WHERE login=\"".mysql_real_escape_string($user)."\" AND password=ENCODE(\"".mysql_real_escape_string($pass)."\",\"".mysql_real_escape_string(ENCRYPTION_SEED)."\")";
$queryresult = $this->db->query($querystatement);
I will need to fix this issue before I can even test the functionality of the if logic using prepared statements.
Your are passing wrong variable for delete query
$stmt3 = $conn->prepare($sql3);
Please refer [ http://www.plus2net.com/php_tutorial/pdo-delete.php ]

->num_rows doesn't work correctly [duplicate]

This question already has answers here:
PHP MYSQLI number of rows doesnt work no errors
(3 answers)
Closed 6 years ago.
I don't understand why $amountOfUsers is showing as 0?
This used to work before I moved to the bind_param function... I was only using query() instad of prepare. But this is a lot safer, I just have trouble understand why this doesn't work, and how to fix it.
$stmt = $mysqli->prepare("SELECT id, expire, status, username FROM username WHERE username= ?");
$stmt->bind_param('s', $username);
$stmt->execute();
//Counting results. 0 = Invalid, 1 = Valid
$amountOfUsers = $stmt->num_rows;
The error I am getting is: $amountOfUsers isn't counting the number of results properly.
$stmt = $mysqli->prepare("SELECT id, expire, status, username FROM username WHERE username= ?");
$stmt->bind_param('s', $username);
$stmt->execute();
// Store the result (so you can get the properties, like num_rows)
$stmt->store_result();
// Get the number of rows
$amountOfRows = $stmt->num_rows;
// Bind the result to variables
$stmt->bind_result($id, $expire, $status, $db_username);
// Process the variables
while($stmt->fetch()) {
printf("%d %s %s %s\n", $id, $expire, $status, $db_username);
}
Sometimes things don't go according to plan. Checking result codes and errors available in your library is usually more efficient for troubleshooting than asking strangers, but hopefully this stranger can help... choose one of these patterns:
A:
$result = $stmt->execute();
if (!$result) { /* handle errors */ }
B:
$stmt->execute();
if ($stmt->errno != 0) { /* handle errors */ }
C (for development troubleshooting only, not code you would leave around):
$stmt->execute();
print_r($stmt->error_list);
More info here and associated pages:
http://www.php.net/manual/en/mysqli-stmt.errno.php
I would never in my life understand why php users are so inclined to the number of rows returned.
Especially if used only as a flag... if any data returned!
Why not to take the very returned data and see?
$sql ="SELECT id, expire, status, username FROM username WHERE username= ?s";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $username);
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();
if ($row)
{
// do whatever
}
I would never understand an inclination to long and windy codes as well.
Why not to get yourself an abstraction library and get everything in one single line?
$sql = "SELECT id, expire, status, username FROM username WHERE username= ?";
if ($row = $db->getRow($sql))
{
// do whatever
}

Categories