PDO not inserting correct data - php

I have this function, which I pass a table name, and data into.
public function quickInsert($table, $data) {
$keys = array_keys($data);
$keysStr = '`'.implode('`,`', $keys).'`';
$valStr = ':'.implode(',:', $keys);
$Sql = "INSERT INTO `$table` ($keysStr) VALUES ($valStr)";
dump($Sql);
$st = $this->connection->prepare($Sql);
foreach ($data as $k => $v) {
dump(':'.$k.' - '.$v);
$st->bindParam(':'.$k, $v);
}
//dump($st->execute());
}
The output from the dumps is
string(114) "INSERT INTO `users` (`email`,`password`,`first_name`,`last_name`) VALUES (:email,:password,:first_name,:last_name)"
string(21) ":email - my#email.com"
string(140) ":password - myHashedPasswordString"
string(17) ":first_name - Tom"
string(17) ":last_name - Hart"
However, when I execute the query, the data in all the fields is the last name (In this case "Hart").
What have I gotten wrong?

$v is overwritten on each iteration of the loop, when it is finished and $st->execute() runs it only contains the last value. Try $st->bindValue() instead of $st->bindParam().

Related

How to change my PHP foreach looped SQL-Insert into a prepared-statement SQL loop?

I have a looped query to do inserts into the MySQL database it works perfectly to do what I need it to do as in it takes all the users inputs in array and then loops them and inputs each into their own row in the database.
$sql_insert_race_history = "INSERT INTO inf_race_history
(`inf_id`,`race_history`, `results`)
VALUES ";
if ($vracehistory != '') {
foreach ($vracehistory as $kay => $value) {
// $sql .= '' | $sql = $sql . '';
$sql_insert_race_history .= "('$inserted_id','{$value}','{$results[$kay]}'),";
}
} else {
$vracehistory = '';
}
// remove last `,` into query;
$sql_insert_race_history = rtrim($sql_insert_race_history, ',');
$countRow = count($_POST['racehist']);
//INSERT INTO THE DATABASE VIA QUERY
$results_racehistory = mysqli_query($vconn, $sql_insert_race_history);
This code works and inserts everything as i need it However i have been told that it is vulnerable to SQL injections attacks, so i have been trying to prevent that by using prepared statements every version I try only so far loops the dont work and it only uploads the very last item in the array
$stmtrace = $conn->prepare("INSERT INTO inf_race_history
(`inf_id`,`race_history`, `results`)
VALUES (?,?,?)");
if ($vracehistory != '') {
foreach ($vracehistory as $kay => $value) {
$stmtrace->bind_param("sss", $inserted_id,$value,$results[$kay]);
}
} else {
$vracehistory = '';
}
// remove last `,` into query;
$sql_insert_race_history = rtrim($stmtrace, ',');
$countRow = count($_POST['racehist']);
//INSERT INTO THE DATABASE VIA QUERY
$stmtrace->execute();
I think it may have something to do with changing it from .= in the foreach loop to just ->bind_param as maybe that is taking away the opportunity to loop it ? tho im not too sure and also how would i echo that i try to echo $stmtrace tho it says method _tostring is not implemented
foreach ($vracehistory as $kay => $value) {
$stmtrace->bind_param("sss", $inserted_id, $value, $results[$kay]);
$stmtrace->execute();
}
You should place execute() inside loop.
bind the params outside the foreach loop, and assign and execute the query when you assign the variables inside the foreach loop. For example
$stmtrace->bind_param("sss", $insertId, $insertValue, $insertKey);
foreach ($vracehistory as $kay => $value) {
$insertId = inserted_id;
$insertValue = $value;
$insertKey = $kay;
$stmtrace->execute();
}
Another note, if you bind an integer, the value of the bind_param method should be 'i'.

How to pass multiple variables in foreach php

I'd like to pass multiple variables in a foreach loop to add the value from $array_sma[] into my database. But so far I can only insert the value from $short_smas, while I'd also like to insert the values from $mid_smas. I have tried nested foreach but it's multiplying the values.
$period = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
$sma = array(6,9);
foreach ($sma as $range) {
$sum = array_sum(array_slice($period, 0, $range));
$result = array($range - 1 => $sum / $range);
for ($i = $range, $n = count($period); $i != $n; ++$i) {
$result[$i] = $result[$i - 1] + ($period[$i] - $period[$i - $range]) / $range;
}
$array_sma[] = $result;
}
list($short_smas,$mid_smas)=$array_sma;
foreach ($short_smas as $short_sma) {
$sql = "INSERT INTO sma (short_sma)
VALUES ('$short_sma') ";
if ($con->query($sql) === TRUE) {
echo "New record created successfully<br><br>";
} else {
echo "Error: " . $sql . "<br>" . $con->error;
}
}
The code in my question works fine i.e. the value from the first sub array ($short_smas) of $array_sma[] gets inserted into the column short_sma of my msql database. The problem I have is when I try to insert the second sub array $mid_smas (see list()) from $array_sma[] in my second column of my database call mid_sma.
I think this is closed to what I want to achieve but still nothing gets inserted in the DB, source: php+mysql: insert a php array into mysql
I don't have any mysql syntax error.
$array_sma[] = $result;
$sql = "INSERT INTO sma (short_sma, mid_sma) VALUES ";
foreach ($array_sma as $item) {
$sql .= "('".$item[0]."','".$item[1]."'),";
}
$sql = rtrim($sql,",");
Main problem is that $short_smas and $mid_smas have different size. Moreover they are associative arrays so either you pick unique keys from both and will allow for empty values for keys that have only one value available or you pick only keys present in both arrays. Code below provides first solution.
// first lets pick unique keys from both arrays
$uniqe_keys = array_unique(array_merge(array_keys($short_smas), array_keys($mid_smas)));
// alternatively we can only pick those present in both
// $intersect_keys = array_intersect(array_keys($short_smas),array_keys($mid_smas));
// now lets build sql in loop as Marcelo Agimóvel sugested
// firs we need base command:
$sql = "INSERT INTO sma (short_sma, mid_sma) VALUES ";
// now we add value pairs to coma separated list of values to
// insert using keys from prepared keys array
foreach ($uniqe_keys as $key) {
$mid_sma = array_key_exists($key, $mid_smas)?$mid_smas[$key]:"";
$short_sma = array_key_exists($key, $short_smas)?$short_smas[$key]:"";
// here we build coma separated list of value pairs to insert
$sql .= "('$short_sma', '$mid_sma'),";
}
$sql = rtrim($sql, ",");
// with data provided in question $sql should have string:
// INSERT INTO sma (short_sma, mid_sma) VALUES, ('3.5', ''), ('4.5', ''), ('5.5', ''), ('6.5', '5'), ('7.5', '6'), ('8.5', '7'), ('9.5', '8'), ('10.5', '9'), ('11.5', '10'), ('12.5', '11')
// now we execute just one sql command
if ($con->query($sql) === TRUE) {
echo "New records created successfully<br><br>";
} else {
echo "Error: " . $sql . "<br>" . $con->error;
}
// don't forget to close connection
Marcelo Agimóvel also suggested that instead of multiple inserts like this:
INSERT INTO tbl_name (a,b,c) VALUES (1,2,3);
its better to use single:
INSERT INTO tbl_name
(a,b,c)
VALUES
(1,2,3),
(4,5,6),
(7,8,9);
That's why I append value pairs to $sql in foreach loop and execute query outside loop.
Also its worth mentioning that instead of executing straight sql its better to use prepared statements as they are less prone to sql injection.

in php Foreach loop moves to the wrong key

I have the following array structure
jobs = {70811 ={....invoices = { A="A",...},...},...}
Then I have two nested loops. The outer nested loop seeks each job # in this case 70811. The inner loop then seeks each invoice listed for the job.
in each loop I query one of the tables
foreach ($this->p['jobs'] as $job => $value) {
$sql = 'select concat(sum(i.`AMOUNT`))as `amount`, ...
from `invoice` i
where i.`JOBID` = '.$job.'
group by i.`tracknum` = "'.$this->cTrackKey.'"';
$cmeJobEdits = 0;
if ($result = $db->query($sql))
{
if ($result->num_rows > 0)
{
$this->budget = mysqli_fetch_all( $result, $resulttype = MYSQLI_ASSOC );
$subTot = 0;
for ($i=0; $i<count($this->budget);$i++)
{
$subTot += $this->budget[$i]['amount'];
}
...
unset($i);
$xsql = 'update `cmejob` set `balance` = '.$this->budget[0]['balance'].',... where `jobid` = '.$job;
if (!$result = $db->query($xsql))
{
throw new Exception("Query to update budget failed!");
}else{
$cmeJobEdits++;
}
unset($xsql);
}
}else{
throw new Exception("Query to get billed amounts for this job failed! "`enter code here`);
}
unset($sql);
unset($value);
}//end loop updating cme jobs
My problem is this the outer query where the $job variable is not the next job # but the nested array key "invoices" as shown below.
As shown in the code I tried unsetting the query and key variables in the loops with no success.
select concat(sum(i.`AMOUNT`))as `amount`, ...
from `invoice` i
where i.`JOBID` = invoices //this is the value of the variable $job
group by i.`tracknum` = "'.$this->cTrackKey.'"';
Here is the var_dump($this->p['jobs'] of the values as you requested. Is this how you prefer seeing it
array(1) { [84528]=> array(6) { ["thisBudget"]=> string(4) "0.00" ["thisBilled"]=> string(9) "44,633.80" ["thisSum"]=> string(9) "28,003.00" ["thisBalance"]=> string(10) "-72,636.80" ["invoices"]=> array(1) { ["A"]=> string(1) "A" } ["DORMANT"]=> string(0) "" } }
The problem has been resolved.
As usual the error occurred in code not shown. The code above added an 'invoices' element to the $this->p['jobs'] array when it should have been added somewhere else.
now the loop works as described.

Php Update using PDO

I'm trying to build a custom class to manage operations with database. I'm a beginner with OOP so if you have any suggests please tell me. By the way, i have an update method which took as parameter the name of the table, the fields to update, the values with which i want to update the fields and the fields and values to put in where clause of query.
At this time, i have two distinct arrays, one for the set part and one for the where part.
I build the query string like so PDOStatement Object ( [queryString] => UPDATE Ordini SET Nome=':Nome', Cognome=': Cognome', Telefono=': Telefono' WHERE ID=':ID' )
Now i would like to bind the params to the variables and execute the query and that's the problem. I try this way but the query don't update the fields.
- In $values i have the values i want to bind to variables in the SET part
- In $wv i have the values i want to bind to variables in the WHERE part
- In $fieldsQuery i have the placeholders for the SET part(":Nome" for example)
- In $fieldsWhere i have the placeholders for the WHERE part
How can i bind in the right way the placeholders with the variables?
public function update($table=NULL, $fieldsQuery=NULL, $fieldsValues = NULL, $whereFields=NULL, $whereValues=NULL, $whereOperators = NULL)
{
if($fieldsQuery != NULL)
$fields = explode(",", $fieldsQuery);
if($fieldsValues != NULL)
$values = explode(",", $fieldsValues);
if($whereFields != NULL)
$wf = explode(",", $whereFields);
if($whereValues != NULL)
$wv = explode(",", $whereValues);
$fieldsQuery = array_map(function($field) { return ":$field";}, $fields);
$bindValuesSet = array_combine($fieldsQuery, $values);
//return an array in which every field is => Fieldname=':Fieldname'
$bindSetInitial = array_combine($fields, $fieldsQuery);
//transform every item in array from field to :field
$fieldsWhere = array_map(function($field) { return ":$field";}, $wf);
$bindValuesWhere = array_combine($fieldsWhere, $wv);
$bindWhereInitial = array_combine($wf, $fieldsWhere);
//implode an array mantaining both key and value
$fieldsValues = implode(', ', array_map(function ($v, $k) { return sprintf("%s='%s'", $k, $v); }, $bindSetInitial, array_keys($bindSetInitial)));
$fieldsWhere = implode(', ', array_map(function ($v, $k) { return sprintf("%s='%s'", $k, $v); }, $bindWhereInitial, array_keys($bindWhereInitial)));
$query = $this->db->prepare('UPDATE ' . $table . ' SET ' . $fieldsValues . ' WHERE ' . $fieldsWhere);
$query->bindParam(':Nome', $values[0]);
$query->bindParam(':Cognome', $values[1]);
$query->bindParam(':Telefono', $values[2]);
$query->bindParam(':ID', $wv[0], PDO::PARAM_INT);
$query->execute();
print_r($query->debugDumpParams());
}
':Nome' is not a placeholder for a prepared statement. It's just a string ':Nome'
Placeholder is :Nome (without `) and without any spaces, tabs etc.
I.e. : Nome is not a placeholder too.
So, you query should be:
UPDATE Ordini SET Nome=:Nome, Cognome=:Cognome, Telefono=:Telefono WHERE ID=:ID
And thanks to #Fred-ii- - read error handling section of PDO

Insert array into MySQL

I am super confused and have been searching. But as the title suggests I am trying to enter an array.
My question is how do I get this array to import into the database? As of now with the current script, it only imports the first record and not the rest. Here also, I am able to import other values within the same array this is a JSON call by the way and its already being decoded.
foreach ($output as $key => $value) {
if (isset($output[$key]["stats"]["damage_given"]["vehicle"])) {
$damage_given[$key] = $output[$key]["stats"]["damage_given"]["vehicle"];
foreach ($damage_given[$key] as $vehicle_name) {
$vehicle_dmg_id = $vehicle_name['id'];
$vehicle_dmg_name = $vehicle_name['name'];
$vehicle_dmg_value = $vehicle_name['value'];
$vehicle_dmg_faction_nc = $vehicle_name['faction']['nc'];
$vehicle_dmg_faction_tr = $vehicle_name['faction']['tr'];
$vehicle_dmg_faction_vs = $vehicle_name['faction']['vs'];
}
}
}
$add_dmg_veh = "INSERT INTO damage_given(character_number, vehicle_id,
vehicle_name, total_value, vehicle_faction_nc, vehicle_faction_tr,
vehicle_faction_vs) VALUES ('$character_id[$key]', '$vehicle_dmg_id',
'$vehicle_dmg_name','$vehicle_dmg_value', '$vehicle_dmg_faction_nc',
'$vehicle_dmg_faction_tr','$vehicle_dmg_faction_vs')";
Although it is not recommended to store an array in a database, you could serialize() your array to store it in a database. Basically, PHP will convert the array into a specially crafted string, which it can later interpret.
Serialize to store it in the database, and unserialize it to work with it when you pull it out of the database
Note: I say serialization is not recommended, because your database is then not in First Normal Form, specifically because you are storing non-atomic values inside of a particular entry in the database. For this case, I would recommend creating a separate table which can store these values individually, and link the two tables together with a foreign key.
You should be looking about PDO_MySQL and your insert string is outside the loop and should be execute inside it.
You have to iterate through the array and insert every field of the array by it's own.
foreach($array as $value) {
// execute your insert statement here with $value
}
First of all you can't insert array in MySQL as you are doing .. Do as with iterating..
foreach ($output as $key => $value) {
if (isset($output[$key]["stats"]["damage_given"]["vehicle"])) {
$damage_given[$key] = $output[$key]["stats"]["damage_given"]["vehicle"];
foreach ($damage_given[$key] as $vehicle_name) {
$vehicle_dmg_id = $vehicle_name['id'];
$vehicle_dmg_name = $vehicle_name['name'];
$vehicle_dmg_value = $vehicle_name['value'];
$vehicle_dmg_faction_nc = $vehicle_name['faction']['nc'];
$vehicle_dmg_faction_tr = $vehicle_name['faction']['tr'];
$vehicle_dmg_faction_vs = $vehicle_name['faction']['vs'];
// if you wants to use insert query then do here.
$add_dmg_veh = "INSERT INTO damage_given(character_number, vehicle_id,
vehicle_name, total_value, vehicle_faction_nc, vehicle_faction_tr,
vehicle_faction_vs) VALUES ('$character_id[$key]', '$vehicle_dmg_id',
'$vehicle_dmg_name', '$vehicle_dmg_value', '$vehicle_dmg_faction_nc',
'$vehicle_dmg_faction_tr', '$vehicle_dmg_faction_vs')";
}
}
}
try building your insert data in an array and then implode the results into a single query:
<?php
foreach ($output as $key => $value) {
if (isset($output[$key]["stats"]["damage_given"]["vehicle"])) {
$damage_given[$key] = $output[$key]["stats"]["damage_given"]["vehicle"];
foreach ($damage_given[$key] as $vehicle_name) {
$sql[] = "
(
".$vehicle_name['id'].",
".$vehicle_name['name'].",
".$vehicle_name['value'].",
".$vehicle_name['faction']['nc'].",
".$vehicle_name['faction']['tr'].",
".$vehicle_name['faction']['vs']."
)";
}
}
}
$query = "
INSERT INTO damage_given
(
character_number,
vehicle_id,
vehicle_name,
total_value,
vehicle_faction_nc,
vehicle_faction_tr,
vehicle_faction_vs
)
VALUES
".implode(",",$sql)."
";
?>
here is what I got to fix the problem!
$stmt = $dbh->prepare(
"INSERT INTO kills_vehicle (character_number, veh_id, veh_name, veh_total, veh_faction_nc, veh_faction_tr, veh_faction_vs)
VALUES(:char_id, :id, :vehname, :total_value, :faction_nc, :faction_tr, :faction_vs)");
foreach ($output as $key => $value) {
if (isset($output[$key]["stats"]["play_time"]["vehicle"])) {
$character_id[$key] = $output[$key]["id"];
$score_hit_count[$key] = $output[$key]["stats"]["kills"]["vehicle"];
foreach ($score_hit_count[$key] as $row) {
$stmt->bindValue(':char_id', $character_id[$key]);
$stmt->bindValue(':id', $row[id]);
$stmt->bindValue(':vehname', $row[name]);
$stmt->bindValue(':total_value', $row[value]);
$stmt->bindValue(':faction_nc', $row[faction][nc]);
$stmt->bindValue(':faction_tr', $row[faction][tr]);
$stmt->bindValue(':faction_vs', $row[faction][vs]);
$stmt->execute();
}
}
}

Categories