The following script is used to implode values from a multidimensional array and insert into the mysql table. The table contains field data types of varchar and decimal. Since varchar type requires quotes and to avoid selectively placing quotes, I would like to put all values in quotes. How to implement it?
$values = array();
foreach ($data as $rowValues) {
foreach ($rowValues as $key => $rowValue) {
}
$values[] = "(" . implode(', ', $rowValues) . ",'".$date."')";
}
$query = "INSERT INTO mem (memno,loan,subsc,intst, date)
VALUES " . implode (', ', $values);
$result=mysql_query($query) or die();
I want the sql like this
INSERT INTO mem (memno,loan,subsc,intst, date)
values('value1', 'value2', 'valu3','value4','value5')
Don't use user input to build SQL strings - thats how you get SQL injection attacks.
Instead use a prepared statement:
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');
$stmt = $mysqli->prepare("
INSERT INTO mem( memno, loan, subsc, intst, date )
VALUES (?, ?, ?, ?, ?);
");
$stmt->bind_param('sssss', $memno, $loan, $subsc, intst, $date);
edit in response to the comment:
Dynamically binding an array of columns is pretty easy with PDO.
$db =new PDO("mysql:host=localhost;dbname=database;","root","");
/**
* #param PDO $db
* #param string $table - the table to insert into
* #param array $columns - which columns do we want to insert into
* #param array $data - a key/value array of the data we want to insert
* #return bool
*/
function insert_into($db, $table, array $columns, array $data) {
$rows = implode(', ', $fields);
$placeholders = array_map ( function($key){ return ":$key" }, $fields);
$placeholders = implode(', ', $fields);
$sql = "
INSERT INTO $table ($fields)
VALUES ($placeholders);
";
$stmt = $db->prepare($sql);
foreach( $fields as $field) {
$stmt->bindParam(":$field", $data[$field]);
}
return $sth->execute();
}
$inserted = insertInto(
$db
'mem',
array("memno", "loan", "subsc", "intst", "date"),
$data
);
Notice that the columns to insert are defined separately.
If I had used:
array_keys($data);
It would lead to a mass assigment vulnerability if $data comes from user input and is not whitelisted.
You can accomplish the same thing with mysqli but its a bit trickier.
If $rowValues array is as below then you can do like this also.
$rowValues = array(
"memno"=>"a",
"loan"=>"b",
"subsc"=>"c",
"intst"=>"d"
);
$fldStr = array();
$valStr = array();
foreach($rowValues as $key=>$val) {
array_push($fldStr, $key);
$v2 = "'" . $val . "'";
array_push($valStr, $v2);
}
array_push($fldStr, "date");
array_push($valStr, "'" . $date . "'");
$flds = implode(", ", $fldStr);
$vals = implode(", ", $valStr);
$query = "INSERT INTO mem ($flds) values($vals)";
Related
I am trying to generate a single insert statement that will insert multiple rows. I have and array of values, which is what I am wanting to insert into a table that all use the same userkey.
I have tried using a named PDO parameter and binding to that, then passing in the role array during execute but that doesn't work. So I moved on to placeholders, but I can't get that to work either.
I call my function like addUsersRoles(1, [100,101,102]);
And looking at the generated SQL I get:
INSERT user_roles (userkey, roleid) VALUES (?,?),(?,?),(?,?)
Which I think is the correct format for inserting multiple records.
Based up on that, what I am trying to generate is:
INSERT user_roles (userkey, roleid) VALUES (1,100),(1,101),(1,102)
How can I combine the power of PDO's binding to a SQL statement in this manner?
public function addUsersRoles($userkey, $roles = []){
$in = str_repeat('?,', count($roles) - 1) . '?';
$base_user_sql = 'INSERT user_roles (userkey, roleid) VALUES ';
$sql = $base_user_sql;
foreach ($roles as $role) {
//$sql .= "(:USERKEY, $in),"; // Didn't Work
$sql .= "($in),";
}
//Remove trailing comma
$sql = rtrim($sql, ',');
$db = static::getDB();
$stmt = $db->prepare($sql);
//$stmt->bindValue(':USERKEY', $userkey, PDO::PARAM_STR);
return $stmt->execute($roles);
}
You can use placeholders as well. Look at the following example:
public function addUsersRoles(string $userKey, array $roles = []): bool
{
$values = [];
$inputParameters = [':user_key' => $userKey];
foreach ($roles as $index => $role) {
$rolePlaceholder = ':roleid' . $index;
$values[] = sprintf('(:user_key, %s)', $rolePlaceholder);
$inputParameters[$rolePlaceholder] = $role;
}
$sql = 'INSERT INTO user_roles (user_key, roleid) VALUES ';
$sql .= implode(', ', $values);
$db = static::getDB();
$stmt = $db->prepare($sql);
return $stmt->execute($inputParameters);
}
This code will generate a query like this:
INSERT INTO user_roles (user_key, roleid) VALUES (:user_key, :roleid0), (:user_key, :roleid1), (:user_key, :roleid2), (:user_key, :roleid3), (:user_key, :roleid4);
And the $inputParameters will be like this:
[
':user_key' => 'some user key',
':roleid0' => 1,
':roleid1' => 2,
]
You shouldn't use count($roles) when making $in. It's always just ?, ?. You just need the count of roles when repeating that for all the rows. You can use array_fill to create an array of (?, ?) strings, and then implode to put commas between them.
You also need to insert create an array with alternating keys and roles, and use that as the parameters when executing.
public function addUsersRoles($userkey, $roles = []){
$values = implode(',', array_fill(0, count($roles), '(?, ?)'));
$base_user_sql = 'INSERT user_roles (userkey, roleid) VALUES ';
$sql = $base_user_sql . $values;
$keys_and_roles = [];
foreach ($roles as $role) {
$keys_and_roles[] = $userkey;
$keys_and_roles[] = $role;
}
$db = static::getDB();
$stmt = $db->prepare($sql);
return $stmt->execute($keys_and_roles);
}
I've simplified it a bit, but this splits into two parts that are done together. The first is to generate the SQL...
INSERT user_roles (userkey, roleid) VALUES (?,?),(?,?),(?,?)
This code just loops through the roles and adds (?,?), for each one.
The second part is building up the bind data. As the SQL needs a list of the data in the order userkey, roleid pairs, as it's building the SQL, it also adds these values to a data array at the same time.
So the main code comes out as...
public function addUsersRoles($userkey, $roles = []){
$sql = 'INSERT user_roles (userkey, roleid) VALUES ';
$binds = [];
foreach ( $roles as $role ) {
$sql .= "(?,?),";
$binds[] = $userkey;
$binds[] = $role;
}
//Remove trailing comma
$sql = rtrim($sql, ',');
$db = static::getDB();
$stmt = $db->prepare($sql);
return $stmt->execute($binds)
}
(Although I haven't been able to test the execute part).
You should also make sure any errors are being dealt with as well.
I have some SQL queries that use PHP string variables to create the query before PDO prepare().
$connection = new PDO(...);
// Make variable placeholder for each column.
$params = array();
foreach ($row as $col => $value) {
$params[':' . $col] = $value;
}
$columns = implode(', ', array_keys($row));
$values = implode(', ', array_keys($params));
$query = "
INSERT INTO my_table ($columns)
VALUES ($values)
";
$statement = $connection->prepare($query);
$statement->execute($params);
Or something similar with SELECT:
$query = "
SELECT field
FROM my_table
WHERE id IN ($ids)
";
Where the query will become
$query = "
SELECT field
FROM my_table
WHERE id IN (:id0, :id1, :id2)
";
and then the execute() function will pass in the params like array(':id0' => 0, ...).
Is this vulnerable to injection if the part being inserted is just a bunch of placeholders to be used for query preparation? And is there a better way to do this in PHP with PDO?
When binding a dynamic number of parameters, I revert to the ? placeholders. You can do:
$placeholders = implode(',', array_fill(0, count($values), '?'));
$query = "SELECT field FROM my_table WHERE id IN ($placeholders)";
$stmt = $pdo->prepare($query);
$stmt->execute($values);
You still need to do string substitution if the column names are dynamic, as in your INSERT example. Those should be white-listed to prevent injection. But you can use the above mechanism for the values being inserted. You'll need to use
$values = array_values($params);
because ? placeholders can't be filled in from an associative array.
I am trying to check associative array value if it is numeric, here is my code
$data = array('fullname'=>'Salah Saed', 'age'=>'33', 'gender'=>'Female');
public function insert($data, $table){
/*$query = "INSERT INTO `oop_crud`.`customers` (";
$query .= "`fullname` , `age` , `gender` )";
$query .= "VALUES ('".$fullname."', '".$age."', '".$gender."')";
*/
$feilds = array();
$feilds_value = array();
foreach ($data as $field => $field_value){
$feilds[] = $field;
echo $field;
if (is_numeric($field_value)){
$feilds_value[] = $field_value;
}else{
$feilds_value[] = "'".$field_value."'";
}
}
$query = "INSERT INTO ".$table." (";
$query .= implode(',', $feilds).")";
$query .= "VALUES (";
$query .= implode(',',$feilds_value).")";
echo $query;
It returns string, so what is wrong with my code,
in the condition section i used $field_value and this variable has array data, sow how to get array value.
First of all, MySQL inserts are type-independent, so
SET UserAge = '33'
is the same as
SET UserAge = 33
so you would be safer to just add quotes. That said, you're safest if you search for prepared statements using PDO (aka parametrized queries). Take a look at that
http://php.net/is_numeric is supposed to recognize values like 0x539 and 0b10100111001 which may not be recognized by MySQL; you would need to check these cases.
Here is simplified version of your function, in case you want to improve your query generator function,
function insert($data, $table){
$column_sql = '`' . implode('`,`', array_keys($data)) . '`';
$record_sql = "'" . implode("','", $data) . "'";
return "INSERT INTO `{$table}` ({$column_sql}) VALUES ({$record_sql})";
}
Feeding it $data and test will give
INSERT INTO `test` (`fullname`,`age`,`gender`) VALUES ('Salah Saed','33','Female')
NOTE: Need to escape values mysqli_real_escape_string(), i'll leave that upto you, as an exercise :)
how do i convert a string like this:
"joe,anna,kwame,kofi"
to:
"joe","anna","kwame","kofi"
I am trying to use this in an sql statement with an IN clause but i keep getting the error as shown below:
Last SQL query failed:
SELECT * FROM view_salesreport WHERE deleted =0 AND saletype IN (dropoff,pickup)
Can anyone help
// split string into array based on commas
// result: array("joe","anna","kwame","kofi")
$arr = explode(",","joe,anna,kwame,kofi");
// create a string with a "?" for each item in the array
// result: ?, ?, ?, ?
$in = str_repeat('?,', count($arr) - 1) . '?';
// insert $in in SQL query
// result: SELECT * FROM view_salesreport WHERE deleted = 0 AND saletype IN (?, ?, ?, ?)
$sql = "SELECT * FROM view_salesreport WHERE deleted = 0 AND saletype IN ($in)";
// prepares a statement for execution
$stm = $db->prepare($sql);
// executes a prepared statement with array of parameters
$stm->execute($arr);
http://php.net/manual/de/function.explode.php
try something like this:
$output = ''
foreach (explode(',' , $yourString) as $name) {
$output . = $name
}
you can try this:
$string = "joe,anna,kwame,kofi";
$string = str_replace("'","\\'",$string);
$string = "'".str_replace(',',"','",$string)."'";
You can easily use explode() and implode() to get the string format you want. For example:
$initial_string = "joe,anna,kwame,kofi";
// split string into array based on commas
$names = explode(',', $initial_string);
// combine back into string using implode
$query = "SELECT * FROM view_salesreport WHERE deleted =0 AND saletype IN ('" . implode("','", $names) . "')";
<?php
session_start();
include('function.php');
site::db();
$type=$_GET['type'];
$date=$_GET['date'];
$amount=$_GET['amount'];
switch($type) {
case "in_park":
$table = "lot_income";
$col = "date,amount";
$val = $date $type $amount;
break;
}
$sql = mysql_query("INSERT INTO $table ($col) VALUES ('$val')");
if(!$sql) {
die(mysql_error());
}
//header("LOCATION: dashboard.php")
?>
This will not work but im assuming that i will will need to explode the variables val but how to i put the comma in there too so i can put the info in many different field other than just one field.
Change this..
$val=$date $type $amount;
Into this
$val= "'$date', '$amount'";
And thius
$sql=mysql_query("INSERT INTO $table ($col) VALUES ('$val')");
into this
$sql=mysql_query("INSERT INTO $table ($col) VALUES ($val)");
I think you are missing a column in your SQL statement:
$col = "date, type, amount";
You will need to format the SQL values accordingly:
$val = "'$date', '$type', '$amount'";
Concatenate them:
$sql = mysql_query("INSERT INTO $table ($col) VALUES ($val)");
I usually do:
$table = "lot_income";
$data = array(
'date' => "'".mysql_real_escape_string($date)."'", // date
'type' => intval($type), // integer
'amount' => intval($amount), // integer
'text' => "'".mysql_real_escape_string($sometext)."'" // string
// etc
);
// I tend to wrap the following statement in a function for code reuse
$resource = mysql_query(
"INSERT INTO ".$table." (".implode(", ", array_keys($data).")"
. "VALUES (".implode(", ", array_values($data).")"
);
Note: for values escaping (in order to avoid SQL injections), it would be easier/safer to bind variables by using PHP extension PDO or mysqli.