bind parameters in prepared statements - php

I found out earlier today that I am quite behind with using prepared statements. I tried to make a prepared statement to get some data out from my database.
I would like to print all the rows in my database, but I am not quite sure how to do that in my while loop?
<?php
/* Prepare */
if ($stmt = $mysqli->prepare("SELECT * FROM stores")) {
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
/* Bind and execute */
$id = null;
$headline = null;
$description = null;
$place = null;
if (!$stmt->bind_param("i", $id, "s", $headline, "s", $description, "s", $place)) {
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
while ($stmt->fetch()) {
/* Loop through my rows in MySQL and print all rows*/
echo $id, $headline, $description,$place;
}
/* Close Statement */
$stmt->close();
/* Close Connection */
$mysqli->close();
?>

if (!$stmt->bind_param("isss", $id, $headline, $description, $place))
{
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
You'll want to do that. As #Fred-ii said in the comments. You've got the syntax wrong.
How it works is that the first parameter of bind_param is all your data types as one string, then you list your data afterwards. Ensure that you use the right data type and the right amount of parameters.
Update
Having inspected your code further, I realise you haven't use prepare correctly. I'll include a demonstration below so you can use it as a guide.
$stmt = $mysqli->prepare("SELECT * FROM myTable WHERE id = ? AND name = ?");
if (!$stmt->bind_param("is", $id, $name))
{
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!$stmt->execute())
{
echo "Execution failed: (" . $stmt->errno . ") " . $stmt->error;
}
The question marks delineate each variable. This means that you put a ? where you want a variable to go.
Then you use bind_param to list your data types (as stated above) with your variables or data following.
Update 2
$errors = array(); // store errors here
$stmt = $mysqli->prepare("SELECT name FROM myTable WHERE id = ?"); // prepare our statement
// check that our parameters match, if not then add error
if (!$stmt->bind_param("i", $id))
{
array_push($errors, "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error);
}
// if no errors and statement fails to run
if (count($errors) <= 0 && !$stmt->execute())
{
array_push($errors, "Execution failed: (" . $stmt->errno . ") " . $stmt->error);
}
// no statement errors
if (count($errors) <= 0)
{
$stmt->bind_result($name); // store the results of the statement in this variable
// iterate through each row of the database
while ($stmt->fetch())
{
echo $name;
}
}
// report the errors
else
{
echo "<h3>Errors</h3>";
foreach ($errors as $error)
{
echo "<p>$error</p>";
}
}
$errors = array()
Here I create an array that will hold all of our error messages.
array_push($errors, "...")
The array_push function will add a variable to the array in the syntax of array_push($array, $var) where $array is the array that will have items added, and $var is the item you want to add.
I use this so that I can add errors in a neat way, that can be later iterated.
count($errors)
The count function will count the number of elements in an array.
I use this to see if any errors have been added to the array. When I initialise $errors there are no elements in it so it will return 0.
$stmt->bind_result($name)
This is written outside of the while loop since it is used to tell the statement that we want to store all of the column name inside this variable named $name.
while ($stmt->fetch())
This will iterate through each row in the database. Each iteration of the while loop will be one row of the database. In my example, I simply echoed the value for the name column.
It is possible to store more than one column. Just add the column in the SQL query (SELECT col1, col2, col3 FROM mytable) and then store each column in a variable in bind_result ($stmt->bind_result($col1, $col2, $col3);. Note that they do not have to be the same name as the column; this is also valid $stmt->bind_result($myVar, $someVar, $anotherVar);).
foreach ($errors as $error)
foreach takes an array and iterates through it, storing each iteration in the variable following as.
In this instance we have errors stored in an array named $errors, and we store each one in $error and write it in a paragraph tag.

Related

Mysql fetch() returns FALSE

I have currently a problem on streaming results from a mysql table. This table has more than 10,000,000 rows. And the structure
ID, IndexField1, Data1
With Primaryindex on ID and Index on IndexField1.
In PHP I tied to stream parts of the data (about 7 Mio) to calculate and verify some parts. For this reason I hava a callback which is been called for every single response.
public function streamForIndexedColumn(int $columnId, callable $callback){
$stmt = NULL;
$sql = "SELECT id, indexedField, data1 FROm myTable WHERE indexedField1 = ?;";
if (! ($stmt = $this->mysqlConn->prepare ( $sql ))) {
throw new Exception("ERROR");
}
try {
if (! $stmt->bind_param ( "i", $columnId)) {
throw new Exception( "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error );
}
$item = new Item ();
if (!$stmt->bind_result($item->id,$item->indexfield1,$item->data1)) {
throw new Exception( "Binding output parameters failed: (" . $stmt->errno . ") " . $stmt->error );
}
if (! $stmt->execute ()) {
throw new Exception("Execute failed: (" . $stmt->errno . ") " . $stmt->error );
}
$cnt = 0;
while ( $row = $stmt->fetch() ) {
$cnt++;
$callback($cnt, $item);
}
if ($row ===FALSE){
throw new Exception("MySQL Error: (" . $stmt->errno . ") " . $stmt->error );
} finally{
$stmt->close ();
}
}
This runs sometimes for several hours. Sometimes it is running, sometimes it is failing with message "MySQL Error: (0) "
Are I am getting the error reason in a wrong way? Are there any configurable Limits on the server or client which may produce this error?
I am using Mysql 5.17.19 and PHP 7.0.29.
The exception in $row === FALSE will always be thrown because after it fetches all rows, $row will be false.
$stmt->errno will return 0 because (Quoted from the docs: http://php.net/manual/en/mysqli.errno.php)
Returns the error number from the last MySQL function, or 0 (zero) if no error occurred.

Prepared statement adding empty lines to mysql using PHP

I am a bit lost with my prepared statement. My goal it to read a simple small csv file (100 lines and about 10 columns) into a mysql database.
Since I couldn't get that to work I simplified the mysql table to one column for now (OrderUuid). The first part of the code I hardcoded a testvalue for my OrderUuid variable, which gets added to mysql fine. However, when I take the column value form the csv file (line[0]), nothing (an empty string I think) gets added to the db table.
Here is my code:
while(($line = fgetcsv($csvFile)) !== FALSE){
//This works!
$OrderUuid = "Test";
$insertQry2 = $conn->prepare("INSERT INTO orders_test (OrderUuid) VALUES (?)");
$insertQry2->bind_param("s", $OrderUuid);
if(!$insertQry2->execute()){trigger_error("there was an error....".$conn->error, E_USER_WARNING);}
//This doesn't
$OrderUuid = $line[0];
echo $OrderUuid."<br>"; //Returns something like: d17e91d5-63b9-4a56-a413-3274057073c7
$insertQry3 = $conn->prepare("INSERT INTO orders_test (OrderUuid) VALUES (?)");
$insertQry3->bind_param("s", $OrderUuid);
if(!$insertQry3->execute()){trigger_error("there was an error....".$conn->error, E_USER_WARNING);}
}
Any help would be appreciated!
Thanks!
Norm
EDIT 1:
Thanks for all the tips guys! I rewrote the code, but unfortunately the script is still inserting empty strings into my table. There is no error messages whatsoever.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$flag = true;
$data = array();
while(($line = fgetcsv($csvFile)) !== FALSE){
if($flag) { $flag = false; continue; }
$data[] = $line;
}
if (!($stmt = $conn->prepare("INSERT INTO orders_test (OrderUuid) VALUES (?)"))) {
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
}
if (!$stmt->bind_param("s", $data[0][0])) {
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
foreach($data as $dat) {
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
Here is my super simple table:
CREATE TABLE orders_test (
OrderUuid varchar(500) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
For anyone that is interested, it was actually super simple in the end. The file contained some letters that the database interpreted as lots of line breaks I think. Therefore applying
strip_tags
did the trick.

php mysql prepared statements loop array

my problem is that I want to loop through an array and insert every entry of that array into another column of an mySQL table. To be honest, I'm not sure if that's the best way to design my database, but that's one way I could imagine, it works. If someone has a better idea of how to do it or a link for best practice or something, that would be awesome.
So what I want to do: I have a form where someone can register to offer a food delivery service. He can enter name etc. and up to 10 offers (limitation of the database table). These information should be insert into the table 'anbieter' into the fields 'angebot_0' , 'angebot_1' ...
So what I did is:
if (isset($_POST['register_offer']) and isset($_POST['anbieter-email'])){
$name = $loc = $cat = $email = $password ="";
$angebot = array();
// fill all variables
$name = test_sql($_POST['anbieter-name']);
$email = test_sql($_POST['anbieter-email']);
$password = test_sql($_POST['anbieter-password']);
$loc = test_sql($_POST['anbieter-loc']);
$cat = test_sql($_POST['anbieter-cat']);
// fill $angebot with all given angebot[] entries
foreach($_POST['angebot'] as $ang) {
$angebot[] = test_sql($ang);
}
if(!empty($name) and !empty($loc) and !empty($email) ){
/* decrypt password */
$password = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]);
// insert name, email, password, location and category into database
/* Prepared statement, stage 1: prepare */
if (!($stmt = $conn->prepare("INSERT INTO anbieter (anbieter_name, anbieter_email, anbieter_password, anbieter_loc, anbieter_cat) VALUES (?, ?, ?, ?, ?)"))) {
echo "Prepare failed: (" . $stmt->errno . ") " . $stmt->error;
}
/* Prepared statement, stage 2: bind and execute */
if (!$stmt->bind_param('sssss', $name, $email, $password, $loc, $cat)) {
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
$userid = $stmt->insert_id;
// safe all angebot[] entries to database - angebot[0]-> angebot_0
for($x=0; $x < count($angebot) ; $x++) {
$upd = $conn->prepare("UPDATE anbieter SET angebot_".$x." = ? WHERE abieter_ID = ? ");
$upd->bind_param('si', $angebot[$x], $userid);
$upd->execute();
}
So when I do this, I get the error:
Fatal error: Call to a member function bind_param() on boolean in ...
It's a super bad way to do that by using $x to name different fields of the table, but that's the only way I could think of it works :/
I hope someone can help me here! :)
Thanks a lot!
My suggestion instead on single record update query multiple times you can do it in a single query,
Eg:
$query = "UPDATE anbieter SET";
for ($x = 0; $x < count($angebot); $x++) {
$query .= " angebot_" . $x . " = '" . $angebot[$x] . "', ";
}
echo $query .= " WHERE abieter_ID = " . $userid;
So thanks for you help, but it didn't help much :/
After trying some other possibilties, I solved it like:
$x = 0;
foreach($angebot as $offer){
if (!($upd = $conn->prepare("UPDATE anbieter SET angebot_".$x." = '". $offer. "' WHERE anbieter_ID = " . $userid))) {
echo "Prepare failed: (" . $upd->errno . ") " . $upd->error;
}
/* Prepared statement, stage 2: bind and execute */
if (!$upd->execute()) {
echo "Execute failed: (" . $upd->errno . ") " . $upd->error;
}
$x = $x+1;
}
Maybe it will help someone else :)

Need help fetching an array from a prepared statment

I am new to using prepared statement with PHP. I am trying to get the value of "full_name"... So far I am stuck over here. Can anyone please help figure this out? Thanks!
if($db->connect_error){
echo "Connection Error";
}
$id = 834;
$stmnt = $db->prepare("SELECT * FROM checkout_page where id = ?");
$stmnt->bind_param("i", $id);
if (!$stmnt->execute()) {
echo "Execute failed: (" . $stmnt->errno . ") " . $stmnt->error;
}
$row = $stmnt->fetch();
You need to use bind_result to bind variables to the columns you want. Then each time you call fetch(), those variables will be updated with the next row's values. fetch() with mysqli does not return you the row/result.
This means you cannot use SELECT *. You need to specify which fields you want.
if($db->connect_error){
echo "Connection Error";
}
$id = 834;
$stmnt = $db->prepare("SELECT full_name FROM checkout_page where id = ?");
$stmnt->bind_param("i", $id);
if (!$stmnt->execute()) {
echo "Execute failed: (" . $stmnt->errno . ") " . $stmnt->error;
}
$stmnt->bind_result($full_name);
$stmnt->fetch();
echo $full_name;
Or, if you have the mysqlnd driver installed, you can use get_result() to get a result set just like if you had ran a normal query, not a prepared statement.
if($db->connect_error){
echo "Connection Error";
}
$id = 834;
$stmnt = $db->prepare("SELECT * FROM checkout_page where id = ?");
$stmnt->bind_param("i", $id);
if (!$stmnt->execute()) {
echo "Execute failed: (" . $stmnt->errno . ") " . $stmnt->error;
}
$result = $stmnt->get_result();
$row = $result->fetch_assoc();
echo $row['full_name'];

How do I get a result from a prepared statement using PHP? [duplicate]

This question already has answers here:
Using fetch_assoc on prepared statements
(3 answers)
Closed last year.
I am able to get the result from a standard SQL query however when it comes to prepared statements I am fine up until it comes to getting the result from the query.
As background the query will result with more than one row.
$sql = "SELECT * FROM blog WHERE ID=?";
if (!$stmt = $con -> prepare($sql)) {
echo "Prepare failed: (" . $con->errno . ") " . $con->error;
}
if (!$stmt->bind_param("i", $_GET["ID"])) {
echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
while($row = $stmt->fetch_assoc()){
$blog_title = $row['title'];
$blog_body = $row['body'];
$blog_blurb = $row['blurb'];
$blog_date = $row['posted'];
$blog_tags = $row['tags'];
}
This results in
Fatal error: Call to undefined method mysqli_stmt::fetch_assoc()
However, I have tried what was outlined in the PHP manual but have not succeeded.
Here is better way to do it.
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mydatabase = new mysqli('localhost', 'root', '', 'database');
$id = $_GET['id'];
$stmt = $mydatabase->prepare("SELECT * FROM `blog` where ID = ?");
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result(); //get the results
while ($row = $result->fetch_assoc()) {
echo $row['whatever']; //do whatever here
}
If get_result() doesn't exist in your installation, use this:
$stmt->bind_result($column1, $column2);
while ($stmt->fetch()) {
echo $column1;
echo $column2;
}

Categories