I apologise if the title is poor.
I have been researching Prepared Statements and found the following code here:
/* Create a new mysqli object with database connection parameters */
$mysqli = new mysqli('localhost', 'username', 'password', 'db');
if(mysqli_connect_errno()) {
echo "Connection Failed: " . mysqli_connect_errno();
exit();
}
/* Create a prepared statement */
if($stmt = $mysqli -> prepare("SELECT priv FROM testUsers WHERE username=?
AND password=?")) {
/* Bind parameters
s - string, b - blob, i - int, etc */
$stmt -> bind_param("ss", $user, $pass);
/* Execute it */
$stmt -> execute();
/* Bind results */
$stmt -> bind_result($result);
/* Fetch the value */
$stmt -> fetch();
echo $user . "'s level of priviledges is " . $result;
/* Close statement */
$stmt -> close();
}
/* Close connection */
$mysqli -> close();
The part that I don't understand, is how in the SQL Query "SELECT priv FROM testUsers WHERE username=?
AND password=?"), the system knows what the username and password is. I know that the ? marks are placeholders, and below is also confusing me a bit:
$stmt -> bind_param("ss", $user, $pass);
Because I do not see how the $user and $pass have been defined at any point, and thus how the SQL query will substitute the $user and $pass for an actual string. If that makes sense. Where have these values come from? Where are they in this example?
That's because they aren't. This is probably just an example how to use the script. You will have to define the $user and $pass variables by yourself, for example from an $_POST variable of some sort.
The bind_param function handles the arguments. You have to add the same amount of arguments to the query as you put question marks in it. Than the parser in the core of MySQLi can add the arguments safely to the query.
They are being matched by order. Same logic in string building ("{0} is greater than {1}", "5", "3") becomes 5 is greater than 3. So with parameters
$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);
they are all ordered and matches with columns.
If the original script writer had register_globals ON, e.g. in a previous version of PHP, then the user and pass were passed in from the form in the same way as $_POST['user'] and $_POST['pass']. I offer that you can replace them now and move on.
Related
I'm getting:
Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't
match number of fields in prepared statement in
E:\XAMPP\htdocs\account\lib\register.php on line 73
When I use this code:
if($stmt = $conn -> prepare("INSERT INTO login(user, pass) VALUES(?, ?)")) {
/* Bind parameters s - string, b - blob, i - int, etc */
$stmt -> bind_param("ss", $user, $pw);
/* Execute it */
$stmt -> execute();
/* Bind results */
$stmt -> bind_result($user, $pw);
/* Close statement */
$stmt -> close();
$userId = $conn->insert_id;
}
I can't understand, why this happens every time, what is wrong in my code snippet?
You are attempting to bind_result on a statement that is not returning any results.
Remove this line.
$stmt -> bind_result($user, $pw);
I have this code
$con = new mysqli('####', '####', '####', '####');
if(mysqli_connect_errno()){
echo 'Connection Failed:' . mysqli_connect_errno();
exit();
}
//Variables
$user = $_POST['username'];
$zone = $_POST['password'];
$pass = strtoupper(hash("whirlpool", $zone));
//Prepare
if($stmt = $con -> prepare("SELECT * FROM `accounts` WHERE Username=? AND Key=?")){
$stmt -> bind_param("ss", $user, $pass);
$stmt -> execute();
$stmt -> bind_results($result);
$stmt -> fetch();
if($result) {
$_SESSION['username'] = $user;
$url = 'home.php';
echo '<META HTTP-EQUIV=Refresh CONTENT="1; URL='.$url.'">';
} else {
echo 'Login Failed';
}
}
?>
I am new to Prepared statements and I cannot get it to work.
Upon trying to log in I just get a blank white page with no error. I know I am connected to the db because if I remove the prepared statement and do it the unsecured way everything logs in just fine.
Please note. I have just been looking up tutorials on prepared statements so I can learn to code more securely. I am in no way a pro with this. Any tips would be greatly appreciated.
Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't
match number of fields in prepared statement in
C:\xampp\htdocs\newsystem\loginadd.php
That's because you select * (all fields). You should be more specific about the fields you want to get (for example SELECT id FROM ...).
Have a look at examples on PHP doc: 2 fields are selected, 2 parameters for bind_result().
According to #AbrikChakraborty comment you just need add backticks to your field name:
if($stmt = $con -> prepare("SELECT * FROM `accounts` WHERE Username=? AND `Key`=?")){
and according to #caCtus comment:
$stmt -> bind_result($result);
and if you really want to bind unknown number of fields returned you can check this answer or just use PDO.
Verify the actual query, if it fetches the result. I doubt the query itself returns empty result.
"SELECT * FROM `accounts` WHERE Username=$user AND Key=$pass"
I'm getting:
Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't
match number of fields in prepared statement in
E:\XAMPP\htdocs\account\lib\register.php on line 73
When I use this code:
if($stmt = $conn -> prepare("INSERT INTO login(user, pass) VALUES(?, ?)")) {
/* Bind parameters s - string, b - blob, i - int, etc */
$stmt -> bind_param("ss", $user, $pw);
/* Execute it */
$stmt -> execute();
/* Bind results */
$stmt -> bind_result($user, $pw);
/* Close statement */
$stmt -> close();
$userId = $conn->insert_id;
}
I can't understand, why this happens every time, what is wrong in my code snippet?
You are attempting to bind_result on a statement that is not returning any results.
Remove this line.
$stmt -> bind_result($user, $pw);
Here is an example:
if($stmt = $mysqli -> prepare("
INSERT INTO
jos_virtuemart_product_categories
(
virtuemart_product_id,
virtuemart_category_id,
ordering
)
VALUES
(
?,
?,
0
)"))
{
/* Bind parameters
s - string, b - blob, i - int, etc */
$stmt -> bind_param("ii", $pid, $productcategory);
/* Execute it */
$stmt -> execute();
/* Bind results */
$stmt -> bind_result($result);
/* Fetch the value */
$stmt -> fetch();
/* Close statement */
$stmt -> close();
}
Now, if you look at one of my inserts, I am directly inserting 0, and not passing it through a prepare statement.
Is this workable?The reason I am asking is because I have statements with a TON of fields, where many fields are exactly the same for all rows, but only differs in perhaps two or three, which I get from a loop through a result set.
Thanks
If those are the same for all inserts, you can leave them hardcoded in the query - no need to make your code filled with useless things. The cleaner, the better - right?
Furthermore, you can alter the fields so that those values are the DEFAULT values - so that would eliminate the need to put them in the query.
i am using mysqli prepared statement to insert record in the table like this
$link = mysqli_connect('localhost', 'my_user', 'my_password', 'world');
/* check connection */
if (!$link) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);
$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;
/* execute prepared statement */
mysqli_stmt_execute($stmt);
if(mysqli_stmt_affected_rows($stmt) > 0){
//if insert is successful then get the insrted id.
}
/* close statement and connection */
mysqli_stmt_close($stmt);
/* close connection */
mysqli_close($link);
and would like to get the last inserted id , as the table has record_num field which is auto increment .
so my question is should i place connection name or the statement name inside the function.
i.e
1)
echo mysqli_insert_id($link);
Source: http://php.net/manual/en/mysqli.insert-id.php
2)
echo mysqli_stmt_insert_id($stmt);
Source: http://php.net/manual/en/mysqli-stmt.insert-id.php
which one is correct ?
which one will give me last insrted id by the $stmt ?
there are no other inserts are being done using the same stmt one the same page..*
Update:
according to the note from http://php.net/manual/en/mysqli-stmt.insert-id.php
I am doing only single insert so i guess i can use
mysqli_stmt_insert_id($stmt)
but while doing multiple inserts using prepared statements using
echo mysqli_insert_id($link);
is best practice.
You should use
mysqli_insert_id($link);
Because of this note on the PHP manual you referred us to
mysqli_stmt_insert_id
It should be noted that using mysqli_stmt->insert_id will not result in a unique ID being returned for each execution of a prepared insert statement. In practice, it appears that the first insertion ID is returned. If you are performing multiple inserts with the same prepared statement (one invocation of mysqli_stmt::prepare and multiple invocations of mysqli_stmt::execute() for a given statement), and need to keep the unique ID for each insert, use mysqli_connection->insert_id.
for procedural language you need to use below code,
mysqli_insert_id($link));
yes as you mention in 1 point.
Correct is 1) - link, as stated in documentation:
http://php.net/manual/en/mysqli.insert-id.php