MySQLi prepared statement & foreach loop [duplicate] - php

This question already has answers here:
Best way to INSERT many values in mysqli?
(4 answers)
Closed 1 year ago.
I'm struggling to revise the following (which works) to use a prepared statement:
echo "<div class=\"debug\">
<h4>values \$_POSTed from *LINE-ITEMS TABLE* in input.php:</h4>
<table>";
foreach ($_POST['date'] as $i => $value) {
$invNum = $_POST['invNum'];
$date = $_POST['date'][$i];
$hours = $_POST['hours'][$i];
$rate = $_POST['rate'][$i];
$dateTotal = $_POST['dateTotal'][$i];
echo "<tr>
<td>".$i."</td>
<td>".$date."</td>
<td>".$hours."</td>
<td>".$rate."</td>
<td>".$dateTotal."</td>
</tr>";
$query = "INSERT INTO Invoice_Line_Items SET
INVOICE_NUMBER = '$invNum',
DATE = '$date',
HOURS = '$hours',
RATE = '$rate',
DATE_TOTAL = '$dateTotal'
ON DUPLICATE KEY UPDATE
INVOICE_NUMBER = VALUES(INVOICE_NUMBER),
DATE = VALUES(DATE),
HOURS = VALUES(HOURS),
RATE = VALUES(RATE),
DATE_TOTAL = VALUES(DATE_TOTAL)
";
} // END foreach
echo "</table></div>";
I've been trying to adapt the (working) prepared statement/query running above this in the same page, which inserts a single row into a different table. But this 2nd query (into a different db table) inserts data from multiple (dynamic # of) rows from a line-items table within the source form.
I've been hacking at it for hours but I can't quite sort out how to implement a prepared statement with the line-items loop. I thought it would be along these lines, but this is not inserting.
echo "<div class=\"debug\">
<h4>values \$_POSTed from *LINE-ITEMS TABLE* in input.php:</h4>
<table>";
// this is the line-items table in the form; don't I have to get these values before the query?
foreach ($_POST['date'] as $i => $value) {
$invNum = $_POST['invNum'];
$date = $_POST['date'][$i];
$hours = $_POST['hours'][$i];
$rate = $_POST['rate'][$i];
$dateTotal = $_POST['dateTotal'][$i];
// confirm vars/values
echo "<tr><td>".$i."</td><td>".$date."</td><td>".$hours."</td><td>".$rate."</td><td>".$dateTotal."</td></tr>";
$stmt = $mysqli->stmt_init();
$query = "INSERT INTO Invoice_Line_Items
INVOICE_NUMBER = '$invNum',
DATE = '$date',
HOURS = '$hours',
RATE = '$rate',
DATE_TOTAL = '$dateTotal'
ON DUPLICATE KEY UPDATE
INVOICE_NUMBER = VALUES(INVOICE_NUMBER),
DATE = VALUES(DATE),
HOURS = VALUES(HOURS),
RATE = VALUES(RATE),
DATE_TOTAL = VALUES(DATE_TOTAL)
";
if ($stmt->prepare($query)) {
$stmt -> bind_param("ssddd", $invNum, $date, $hours, $rate, $dateTotal);
$stmt -> execute();
$stmt->close();
} // if $stmt
} // END foreach
echo "</table></div>";
Can someone please shed some light? Much appreciated.
svs

You don't need
$stmt = $mysqli->stmt_init();
You should be able to just call
$stmt = $mysqli->prepare($query);
Another problem is you're setting the query up inside your loop. You shouldn't do that. Move $stmt outside the loop and only run execute inside once you've set your variables up. Finally, you need to add ? so MySQL knows the parameters
$query = "INSERT INTO Invoice_Line_Items
INVOICE_NUMBER = ?,
DATE = ?,
HOURS = ?,
RATE = ?,
DATE_TOTAL = ?
ON DUPLICATE KEY UPDATE
INVOICE_NUMBER = VALUES(INVOICE_NUMBER),
DATE = VALUES(DATE),
HOURS = VALUES(HOURS),
RATE = VALUES(RATE),
DATE_TOTAL = VALUES(DATE_TOTAL)
";
$invNum = $date = $hours = $rate = $dateTotal = '';
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ssddd", $invNum, $date, $hours, $rate, $dateTotal);
foreach ($_POST['date'] as $i => $value) {
$invNum = $_POST['invNum'];
$date = $_POST['date'][$i];
$hours = $_POST['hours'][$i];
$rate = $_POST['rate'][$i];
$dateTotal = $_POST['dateTotal'][$i];
$stmt->execute();
}

Related

When I insert data using PHP it insert more than 10 same data in my table?

I'm trying to create a visitor counter, when user visit the page it will record the time and the number of visitor. But when I refresh the page, my database will be like this:
The code that I do is:
if (empty($counter)){
$counter = 1;
$total = 1;
$time = date('Y-m-d H:i:s');
$sql1 = "INSERT INTO humancount(counter, time, totalHumanCount) VALUES ('$counter', '$time', '$total)";
$result1 = mysqli_query($con, $sql1);
}
//date_default_timezone_set('Asia/Kuala_Lumpur');
$date1 = strtotime("now");
$date2 = strtotime("tomorrow");
echo date("Y-m-d H:i:s", $date1);
echo "<br>";
echo date("Y-m-d H:i:s", $date2);
if ($date1 < $date2){
$plusCounter = $counter + 1;
$plusTotal = $total + 1;
$nextTime = date('Y-m-d H:i:s');
$sql2 = "UPDATE humancount SET counter='$plusCounter', time='$nextTime', totalHumanCount='$plusTotal'";
$result2 = mysqli_query($con, $sql2);
}
I was expecting that it will record the time of the user visit by every row.
This line of code is overwriting every row in the table with the current counter update:
$sql2 = "UPDATE humancount SET counter='$plusCounter', time='$nextTime', totalHumanCount='$plusTotal'";
you should instead insert a new row for each new visitor.
Also, this will always be true:
if ($date1 < $date2)
so you can remove the if statement.
You can do something like this:
//first fetch the last values from the database
$sql0 = "SELECT counter, totalHumanCount FROM humancount ORDER BY time DESC LIMIT 1";
$result = mysqli_query($con, $sql0);
if(mysqli_num_rows($result) > 0) {
$row = mysqli_fetch_assoc($result);
$counter = $row['counter'] + 1;
$total = $row['totalHumanCount'] + 1;
} else {
$counter = 1;
$total = 1;
}
//date_default_timezone_set('Asia/Kuala_Lumpur');
$time = date('Y-m-d H:i:s');
$sql1 = "INSERT INTO humancount(counter, time, totalHumanCount) VALUES ('$counter', '$time', '$total)";
$result1 = mysqli_query($con, $sql1);
Use Where condition in UPDATE query. as per your query every time it will update all rows in table 'humancount'. so add UserID column for unique row and then update row for selected user.
$sql2 = "UPDATE humancount SET counter='$plusCounter', time='$nextTime', totalHumanCount='$plusTotal' WHERE userID = ?";

PHP SQL select uses only the first result of the array in IN statement [duplicate]

This question already has answers here:
How can I bind an array of strings with a mysqli prepared statement?
(7 answers)
Closed 1 year ago.
I am trying to sum a colomn based on the IDs selected from a table that i put in a array. For some reasom only the first ID is used in the Where clausule. When I echo the variable all the ids are there. What am i doing wrong?
$counttheid = array();
$stmt3 = $mysqli->prepare("SELECT
id
FROM account
WHERE level <= '5' AND door = ? AND `group_name` = ? AND betaald = 'Yes'");
$stmt3->bind_param("ss",$usernamesession,$groupname);
$stmt3->execute();
$result3 = $stmt3->get_result(); //only works when nd_mysli is set on the server!
while ($rowid = $result3->fetch_assoc())
{
$counttheid[] = $rowid['id'];
$countid = implode(',', $counttheid); // contains all the ids !!
}
$sql = "SELECT SUM(mobcash) AS totalcash FROM account WHERE id IN (?)
";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i",$countid);
$stmt->execute();
$stmt->bind_result($row['totalcash']);
while($stmt->fetch()) $sumcash = $row['totalcash'];
echo $sumcash; // Somhow only the sum of the first ID of the array !!
echo $countid;// all the ids from the array !!
Not only for the in, but the number of bind parameters will need to match as well.
Try with this example for the code from the while to the execute:
while ($rowid = $result3->fetch_assoc())
{
$counttheid[] = $rowid['id'];
// $countid = implode(',', $counttheid); // contains all the ids !!
}
$in = str_repeat('?,', count($counttheid) - 1) . '?';
$types = str_repeat('i', count($counttheid));
$sql = "SELECT SUM(mobcash) AS totalcash FROM account WHERE id IN ($in)";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param($types, ...$counttheid);
$stmt->execute();
At the bind_param, the part with ...$counttheid, the ... portion is the argument unpacking operator.

prepared statements on loop and rollback if there are errors

I was hoping someone would guide me in the right direction. What I am trying to accomplish is the following:
user uploads a csv file the data is then stored in a multidimensional array $formatted_payments. Then I check the records on the file against the records on the DB. I need to check if the route from the file matches the route on DB if it does for all records then commit all the updates but if there is one mismatch then i need to rollback all the update. I hope this all makes sense. Here is what I did but I haven't tested yet.
Thank you
$conn->autocommit(FALSE);
$route_errors = [];
foreach($formatted_payments as $val){
$sql = "SELECT id, account_no, payment_amount, route_id, payment_date FROM car_payments WHERE payment_date = '".$date."' AND account_no = '".$val['account_no']. "'";
$res = $conn->query($sql);
$data = $res->fetch_object();
if($data){
if($val['amount'] > 0){
if($val['route_id'] != $data->route_id){
$route_errors[] = $val['account_no'];
}else{
$sql = "UPDATE car_payments SET payment_amount = ? charged = ? WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("sss", $val['amount'], 'Si', $data->id);
$stmt->execute();
}
}else{
$sql = "UPDATE car_payments SET payment_amount = ? charged = ?, pending = ? WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ssss", $val['amount'], 'No', 1, $data->id);
$stmt->execute();
}
}
}
if(!empty($route_errors)){
$conn->roll_back();
echo 'The following accounts do not match the route. Records not imported.<br>';
foreach($route_errors as $value){
echo '<li>' . $value . '</li>';
}
}else{
$conn->commit();
}

how to use PDO rowCount() function in foreach?

i need some help , i have simple code like count rows in php, i use PDO ,
so i check if rowCount > 0 i do job if no other job but i have it in foreach function, in first step i get true result but in other i get invalid
so i think it is function like a closeCursor() in PDO but i try and no matter . maybe i do it wrong ?
it is part of my code
public function saveClinicCalendar($post){
$daysItm = '';
$Uid = $post['Uid'];
$ClinicId = $post['ClinicId'];
$type = $post['type'];
$resChck = '';
foreach($post['objArray'] as $arr){
foreach($arr['days'] as $days){
$daysItm = $days.",".$daysItm;
}
$daysItm = substr($daysItm, 0, -1);
$dateTime = $arr['dateTime'];
$sqlChck = 'SELECT * FROM clinic_weeks WHERE dates = :dates AND Uid = :Uid AND category = :category AND Cid = :Cid AND type = :type';
$resChck = $this->db->prepare($sqlChck);
$resChck->bindValue(":dates",$dateTime);
$resChck->bindValue(":Cid",$ClinicId);
$resChck->bindValue(":type",$type);
$resChck->bindValue(":Uid",$Uid);
$resChck->bindValue(":category",$Uid);
$resChck->execute();
$co = $resChck->rowCount();
if($co > 0){
/*UPDATE*/
$sql = 'UPDATE clinic_weeks SET dates = :dates ,time = :time, Cid = :Cid, type = :type, Uid = :Uid, category = :category ';
$res = $this->db->prepare($sql);
$res->bindValue(":dates",$dateTime);
$res->bindValue(":time",$daysItm);
$res->bindValue(":Cid",$ClinicId);
$res->bindValue(":type",$type);
$res->bindValue(":Uid",$Uid);
$res->bindValue(":category",$Uid);
}else{
/*INSERT*/
$sql = 'INSERT INTO clinic_weeks (dates,time, Cid,type,Uid,category) VALUES (:dates,:time, :Cid,:type,:Uid,:category)';
$res = $this->db->prepare($sql);
$res->bindValue(":dates",$dateTime);
$res->bindValue(":time",$daysItm);
$res->bindValue(":Cid",$ClinicId);
$res->bindValue(":type",$type);
$res->bindValue(":Uid",$Uid);
$res->bindValue(":category",$Uid);
}
$res->execute();
$resChck->closeCursor();
$resChck = null;
$daysItm = '';
}
}
what i am doing wrong?
many thanks to Barmar, he suggest me a true answer.
here is a code
$sql = "INSERT INTO clinic_weeks
(`timestam`,`time`,dates,Cid,type,Uid,category)
VALUES
('$timestamp','$daysItm','$dateTime','$ClinicId','$type','$Uid','$Uid')
ON DUPLICATE KEY UPDATE `time` = '$daysItm' ";
I use there "ON DUPLICATE KEY UPDATE" and it`s work perfectly!
instead a big code top of page i make a two line of code.

Catchable fatal error: Object of class PDOStatement could not be converted to string in line 114 [duplicate]

This question already has answers here:
return one value from database with mysql php pdo
(3 answers)
Closed 3 months ago.
I'm trying to add some data to my database, but I'm getting the error Catchable fatal error: Object of class PDOStatement could not be converted to string in /var/www/mandje.php on line 114.
This is the code I'm using:
foreach($_SESSION["cart"] as $id => $value){
$query = $db->query('SELECT * FROM Producten WHERE ProductID ="'.$id.'" ');
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)){
$price = $row['Prijs'];
$ProductID = $row['ProductID'];
}
$sql="INSERT INTO Bestellingsdetail( Bestelnummer, ProductID, Aantal, Prijs)
VALUES ($max,$ProductID,$value,$price)"; //<---- line 114
$count = $db->execute($sql);
I don't really get what's going wrong here. Any help would be much appreciated :)
In the comments, you show the following:
$query = $db->query('SELECT MAX( Bestelnummer ) FROM Bestellingsdetail');
$query->execute();
$max = $query;
$max++;
This is not how you get the result from a query. You are setting $max to a PDOStatement object. You need to fetch() the result in order to use it.
// I've added "AS maxval" to make it easier to get the row
$query = $db->query('SELECT MAX(Bestelnummer) AS maxval FROM Bestellingsdetail');
$max_row = $query->fetch(PDO::FETCH_ASSOC);
$max = $max_row['maxval'];
$max++;
Docs: http://www.php.net/pdo.query
P.S. $query->execute(); is only needed for prepared statements. query() will execute the query immediately.
foreach($_SESSION["cart"] as $id => $value)
{
$query = $db->query('SELECT * FROM Producten WHERE ProductID ="'.$id.'" ');
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC))
{
$price = $row['Prijs'];
$ProductID = $row['ProductID'];
}
$array = array( $max, $ProductID, $value, $price );
$sql->prepare
("
INSERT INTO Bestellingsdetail (Bestelnummer, ProductID, Aantal, Prijs)
VALUES (?, ?, ?, ?)
")
$sql->execute($array);
}
Try:
foreach($_SESSION["cart"] as $id => $value){
$query = $db->query('SELECT * FROM `Producten` WHERE ProductID ="'.$id.'" ');
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)){
$price = $row['Prijs'];
$ProductID = $row['ProductID'];
}
$sql="INSERT INTO `Bestellingsdetail`( `Bestelnummer`, `ProductID`, `Aantal`, `Prij`s)
VALUES ($max,$ProductID,$value,$price)";
$smtp = $db->prepare($sql);
$count = $smtp->execute();
However, try and use the prepared statements as you are defeating the reason of using PDO and could be at risk of injection:
foreach($_SESSION["cart"] as $id => $value){
$query = $db->query('SELECT * FROM `Producten` WHERE ProductID ="'.$id.'" ');
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)){
$price = $row['Prijs'];
$ProductID = $row['ProductID'];
}
$sql="INSERT INTO `Bestellingsdetail`( `Bestelnummer`, `ProductID`, `Aantal`, `Prijs`)
VALUES (:max,:ProductID,:value,:price)";
$stmt = $db->prepare($sql);
$stmt->bindParam(':max', $max);
$stmt->bindParam(':ProductID', $ProductID);
$stmt->bindParam(':value', $value);
$stmt->bindParam(':price', $price);
$count = $smtp->execute();

Categories