How does implode() work with array of variables - php

I have an array of variables:
$values = array($a,$b,$c);
i want to pass this array through this function:
function db_insert($table, $attributes, $values)//insert into the database
{
// $values and takes an array of variables. $attributes is a string "att1, att2,...."
$result = mysql_query("INSERT INTO ' '".$table."' ( '".$attributes."' ) VALUES ( '".implode("','", $values)."' )");
return $result;
}
I pass it like this but it doesn't work:
db_insert("table","a,b,c",$values);
There is no errors but the record is not stored into the database. What is the problem?

You probably want this:
$result = mysql_query("INSERT INTO $table ($attributes) VALUES ('".implode("','", $values)."')");
As a side note you should switch to using mysqli_ functions or PDO instead of mysql_, see why here. You should also read a bit on placeholders and how to use them in your queries.

Related

Mysqli prepared statements build INSERT query dynamically from array

I'm trying to develop my functions in PHP (not OOP), to create a CRUD. The goal is to use the same function to any table, but I got stuck already in the first one. Can't figure how to do this.
What I have right now:
// function to avoid injections
function validate($link, $field){
$valid = mysqli_real_escape_string($link, $field);
$valid = strip_tags($valid);
return $valid;
}
// validate input of array
function sqlWithArray($link,$array){
$return = array();
foreach($array as $field=>$val){
$return[$field] = "'".validate($link, $val)."'";
}
return $return;
}
// Multi insert to any table
function InsertDB($link, $table, array $args){
$rows = sqlWithArray($link,$args);
$keys = "(".implode(array_keys($args)," ,").")";
$values = " VALUES (".implode(array_values($args),", ").")";
$query = "INSERT INTO $table $keys $values";
return $link->execute();
}
I was try to using it as:
InsertDB($link, "test_table", $args); //$args is an array
But I keep getting the following error:
PHP Fatal error: Uncaught Error: Call to undefined method mysqli::execute() in includes\functions.php:37
My 37 line is empty, but 36 and 38 are the following:
$query = "INSERT INTO $table $keys $values";
return $link->execute();
What I'm doing wrong here?
Having such a function is a good idea per se. It indicates that you are a programmer in your heart, not just a tinkerer that writes PHP from ready made blocks like a Lego figure. Such a function can greatly improve your code.
But with great power comes great responsibility. Such a function is a constant danger of SQL injection, through table and field names. You should take care of that. Not to mention it should be properly implemented using prepared statements for the data.
First of all, you will need a general purpose function to execute an arbitrary MySQL query using a query and an array of parameters. I have a simple mysqli helper function for you. It will be a basic function to execute all prepared queries:
function prepared_query($mysqli, $sql, $params, $types = "")
{
$types = $types ?: str_repeat("s", count($params));
$stmt = $mysqli->prepare($sql);
$stmt->bind_param($types, ...$params);
$stmt->execute();
return $stmt;
}
Now we can start constructing the SQL query dynamically. For this we will need a function that would escape identifiers
function escape_mysql_identifier($field){
return "`".str_replace("`", "``", $field)."`";
}
It will make identifiers safe, at least as long as you are using Unocode.
Now we can proceed to creation of the correct SQL string. We will need to create an SQL with placeholders, like this:
INSERT INTO `staff` (`name`,`occupation`) VALUES (?,?)
So let's write a function that would create a query like this
function create_insert_query($table, $keys)
{
$keys = array_map('escape_mysql_identifier', $keys);
$fields = implode(",", $keys);
$table = escape_mysql_identifier($table);
$placeholders = str_repeat('?,', count($keys) - 1) . '?';
return "INSERT INTO $table ($fields) VALUES ($placeholders)";
}
And finally we can write the long-sought crud function:
function crud_insert($conn, $table, $data) {
$sql = create_insert_query($table, array_keys($data));
prepared_query($conn, $sql, array_values($data));
}
called like this
$args = ['name' => "D'Artagnan", "occupation" => 'musketeer'];
crud_insert($link, "test_table", $args);

Insert data with associative array using PDO

Before you duplicate your question, I read all answers that it's has a relation with my question. I'm trying to insert data with associative array for example
<?php
$data = array(
'fname'=>'joe',
'lname'=>'sina'
);
foreach ($data as $key=>$value) {
}
?>
I want to display data like this
/*insert into tblname($key)values($value);
finally the query will appear correctly format */
insert into tblname('fname','lname') values('joe','sina');
You don't need to use foreach here. If you just prepare and bind the query, you can pass $data to the execute() and get the keys by implode() on the keys.
$data = array(
'fname'=>'joe',
'lname'=>'sina'
);
$stmt = $pdo->prepare("INSERT INTO tblname (".implode(', ', array_keys($data)).") VALUES (:".implode(', :', array_keys($data)).")");
$stmt->execute($data);
The keys in the array must match the placeholders in the query (the ones with a colon in front of it). You also had a syntax error in the query, as columns cannot be quoted by singlequotes.

create PHP function for PDO insert query

I have tried to create a function for an SQL/PDO Insert query:
function InsertQuery ($table,$cols,$values) {
global $pdo_conn;
foreach($values as $values2) {
$values2 = $values2;
}
$stmt='INSERT into $table (';
foreach($cols as $cols2) {
$stmt.=" ".$cols2.", ";
}
$stmt.=" ) VALUES ( ";
foreach($cols as $cols2) {
$stmt.=" :".$cols2." ";
}
$stmt.=" ) ";
$stmt2 = $pdo_conn->prepare($stmt);
foreach($cols as $cols2) {
$stmt2->bindParam(':$cols2', $cols2);
}
}
but i am getting the error:
Catchable fatal error: Object of class PDOStatement could not be converted to string in /home/integra/public_html/admin/includes/functions.php on line 30
please be patient with me as i am new to PDO and just used to using MySQL
have i put the prepared statement wrong or my foreach loops?
I believe the statement should look like:
$stmt2 = $pdo_conn->prepare('INSERT into $table (col1) values (:val1)');
$stmt2->bindParam(':$val1', $val);
here is how i called my function:
$col=array('col1');
$val=array('val1');
InsertQuery ("table1",$col,$val);
UPDATE:
Ok here is my new code:
global $pdo_conn;
foreach($values as $values2) {
$values2 = $values2;
}
$stmt='INSERT into '.$table.' (';
foreach($cols as $cols2) {
$stmt.=" ".implode(",", $cols2)." ";
}
$stmt.=" ) VALUES ( ";
foreach($cols as $cols2) {
$stmt.=" :".implode(",", $cols2)." ";
}
$stmt.=" ) ";
$stmt2 = $pdo_conn->prepare($stmt);
foreach($cols as $cols2) {
$stmt2->bindParam(':$cols2', $cols2);
}
but i now get the error about the implode:
Warning: implode() [function.implode]: Invalid arguments passed in /home/integra/public_html/admin/includes/functions.php on line 18
Warning: implode() [function.implode]: Invalid arguments passed in /home/integra/public_html/admin/includes/functions.php on line 22
which i think is because there is nothing to implode as there is only one column and one value
Use type hints to ensure the function arguments are arrays:
function InsertQuery ($table, array $cols, array $values) {
Make sure your PDO connection is accessible. If it's global, you have to declare it (credit to #u_mulder):
global $pdo_conn;
The following does nothing, get rid of it:
foreach($values as $values2) {
$values2 = $values2;
}
Use builtin array functions instead of foreach'ing everything:
$col_list = implode(",", $cols);
$param_list = implode(",", array_fill(1,count($cols), "?"));
Variables don't expand inside single-quotes. You need to use double-quotes (credit to #MichaelBerkowski).
Also, use $stmt for a PDOStatement object, and not for the SQL string. That's confusing.
$sql="INSERT into $table ($col_list) VALUES ($param_list)";
$stmt = $pdo_conn->prepare($sql);
You don't need to write a foreach loop to bindParam() in PDO. You can just pass an array of values to execute(). And you already have the values in an array, so it's really easy:
$stmt->execute($values);
}
For extra safety, make sure to delimit the columns, in case someone uses special characters or a SQL keyword in a column name:
$col_list = implode(",", array_map(function ($c) { return "`$c`" }, $cols));
And make sure the values is in a simple array, not an associative array:
$stmt->execute(array_values($values));
Re your comment:
would you be able to show me how to do the same with select, I'm not sure how it would work as if i have a where clause what would i do with it in the function?
One could for example design a function with an argument $where that is an associative array, whose keys are column names, and whose values are the values you're searching for.
Assume the resulting WHERE clause includes these column/value pairs as AND terms, and all the comparisons are equality.
function SelectQuery($table, array $where) {
global $pdo_conn;
$sql = "SELECT * FROM `$table` ";
$values = null;
if ($where) {
$sql .= "WHERE " . implode(" AND ",
array_map(function ($c) { return "`$c` = ?"; } array_keys($where)));
$values = array_values($where);
}
$stmt = $pdo_con->prepare($sql);
$stmt->execute($values);
}
Of course this supports only a small subset of the possible expressions you can have in a SELECT, but I'm just demonstrating a technique here.
If you want a more fully-feature query builder for PHP, take a look at Zend_Db_Sql or Doctrine QueryBuilder or Laravel query builder.
if anything changes on my server and the PDO stops working i can revert back to MySQL while i fix it.
PDO has been stable since 2005 and it will not stop working, unless you change your PHP environment and disable the extension or the mysql driver or something.
Whereas the ext/mysql extension will stop working. It is currently deprecated and PHP has announced they will remove it in a future version of PHP.
There are a few things going on:
First, $cols and $vals should be arrays, but they are strings.
Quick fix is to make them arrays:
$col = array('col1');
$val = array('val1');
InsertQuery("table1", $col, $val);
Second, $pdo_conn is unknown in the function scope. Make it a parameter or a global.
you can also use this for create query from array:
$myArray = array(
'col1' => 'val1',
'col2' => 'val2'
);
$query = "INSERT INTO table (" . implode(", ", array_keys($myArray)) . ") VALUES (" . implode(", ", $myArray) . ")";
maybe usefull for you
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

PHP PDO - Passing and imploded array to a query placeholder

First of all, I apologize if this is answered somewhere else, but I couldn't find anything.
I have problems with the following code:
function register_user ($register_data) {
global $db;
array_walk ($register_data, 'array_sanitize');
$register_data ['password'] = md5 ($register_data ['password']);
$fields = '`' . implode ('`, `', array_keys ($register_data)) . '`';
$data = '\'' . implode ('\', \'', $register_data) . '\'';
$query = $db -> prepare ("INSERT INTO `users` (:fields) VALUES (:data)");
$query -> bindParam (':fields', $fields);
$query -> bindParam (':data', $data);
$query -> execute ();
}
The problem is that this is executed correctly but the query is not ran and the row is not inserted in the database.
Now, if I just do this:
$query = $db -> prepare ("INSERT INTO `users` ($fields) VALUES ($data)");
//$query -> bindParam (':fields', $fields);
//$query -> bindParam (':data', $data);
$query -> execute ();
everything works like a charm, so I am guessing the problem is with how I am passing data to the placeholders.
Can someone please explain to me why this is not working? I'd like to understand it properly in the first place.
Thanks in advance for any help.
There are two different use cases that could be described as Passing an imploded array to a query placeholder. One is using prepared statements with IN() clause in SQL. this case is already fully covered in this answer.
Another use case is an insert helper function, like one featured in your question. I've got an article that explains how to create an SQL injection proof insert helper function for PDO_MYSQL.
Given such a function is not only adding data values to the query but also table and column names, a prepared statement won't be enough to protect from SQL injection. Hence, such a function will need a helper function of its own, to protect table and field named. Here is one for MySQL:
function escape_mysql_identifier($field){
return "`".str_replace("`", "``", $field)."`";
}
And now we can finally have a function that accepts a table name and an array with data and runs a prepared INSERT query against a database:
function prepared_insert($pdo, $table, $data) {
$keys = array_keys($data);
$keys = array_map('escape_mysql_identifier', $keys);
$fields = implode(",", $keys);
$table = escape_mysql_identifier($table);
$placeholders = str_repeat('?,', count($keys) - 1) . '?';
$sql = "INSERT INTO $table ($fields) VALUES ($placeholders)";
$pdo->prepare($sql)->execute(array_values($data));
}
that can be used like this:
prepared_insert($pdo, 'users', ['name' => $name, 'password' => $hashed_password]);
the full explanation can be found in the article linked above, but in brief, we are creating a list of column names from the input array keys and a list of comma separated placeholders for the SQL VALUES() clause. And finally we are sending the input array values into PDO's execute(). Safe, convenient and concise.

Inserting array values into MySQL

I tried to find another question with the answer to this but I've had no luck. My question is basically...will this work?
$insert_tweets = "INSERT INTO tweets (
'id',
'created_at',
'from_user_id',
'profile_image',
'from_user',
'from_user_name',
'text'
) VALUES (
{$user_data[$i]["id"]},
{$user_data[$i]["created_at"]},
{$user_data[$i]["from_user_id"]},
{$user_data[$i]["profile_image"]},
{$user_data[$i]["from_user"]},
{$user_data[$i]["from_user_name"]},
{$user_data[$i]["text"]}
)"
for($i=0;$i<count($user_data);$i++){
mysqli_query($mysqli,$insert_tweets);
}
$user_data is a multi-dimensional array, the first level of which is numeric, the subsequent level is associative.
Also, what would be the best way to "database prepare"/sanitize the associative array variables prior to insertion? I don't anticipate any malicious data but it is always possible.
for($i=0;$i<count($user_data);$i++){
$insert_tweets = "INSERT INTO tweets ('id','created_at','from_user_id','profile_image','from_user','from_user_name','text') VALUES ({$user_data[$i]["id"]},{$user_data[$i]["created_at"]},{$user_data[$i]["from_user_id"]},{$user_data[$i]["profile_image"]},{$user_data[$i]["from_user"]},{$user_data[$i]["from_user_name"]},{$user_data[$i]["text"]})";
mysqli_query($mysqli,$insert_tweets);
}
This should work
Yes, it will work, but the best way to do this would be to use PDO.
You can create nameless parameters in your prepare statement and then just pass in a array to bind values to those params.
$data = array('val1', 'val2');
$query = $db->prepare("INSERT INTO table (col1, col2) VALUES (? , ?)");
$query->execute($data);
PDO will escape the input values for you.
Here's a tutorial on PDO to get you started
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/
Here is my suggestion on sanitizing your array:
What i do is create a basic function for sanitizing data:
function array_sanitize(&$item){
$item = mysql_real_escape_string($item);
}
Then you can use the array_walk() to sanitize your array with your new function. (php manual refrence)
and sanitize by passing in your array like this:
array_walk($user_data, 'array_sanitize');

Categories