Is there any way to accomplish the following in Wordpress with $wpdb->insert or
$wpdb->query($wpdb->prepare)):
INSERT into TABLE (column1, column2, column3)
VALUES
('value1', 'value2', 'value3'),
('otherval1', 'otherval2', 'otherval3'),
('anotherval1', 'anotherval2', 'anotherval3')
...etc
OK, I figured it out!
Setup arrays for Actual Values, and Placeholders
$values = array();
$place_holders = array();
the initial Query:
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES ";
Then loop through the the values you're looking to add, and insert them in the appropriate arrays:
foreach ( $_POST as $key => $value ) {
array_push( $values, $value, $order_id );
$place_holders[] = "('%d', '%d')" /* In my case, i know they will always be integers */
}
Then add these bits to the initial query:
$query .= implode( ', ', $place_holders );
$wpdb->query( $wpdb->prepare( "$query ", $values ) );
You can also use this way to build the query:
$values = array();
// We're preparing each DB item on it's own. Makes the code cleaner.
foreach ( $items as $key => $value ) {
$values[] = $wpdb->prepare( "(%d,%d)", $key, $value );
}
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES ";
$query .= implode( ",\n", $values );
I have came across with this problem and decided to build a more improved function by using accepted answer too:
/**
* A method for inserting multiple rows into the specified table
*
* Usage Example:
*
* $insert_arrays = array();
* foreach($assets as $asset) {
*
* $insert_arrays[] = array(
* 'type' => "multiple_row_insert",
* 'status' => 1,
* 'name'=>$asset,
* 'added_date' => current_time( 'mysql' ),
* 'last_update' => current_time( 'mysql' ));
*
* }
*
* wp_insert_rows($insert_arrays);
*
*
* #param array $row_arrays
* #param string $wp_table_name
* #return false|int
*
* #author Ugur Mirza ZEYREK
* #source http://stackoverflow.com/a/12374838/1194797
*/
function wp_insert_rows($row_arrays = array(), $wp_table_name) {
global $wpdb;
$wp_table_name = esc_sql($wp_table_name);
// Setup arrays for Actual Values, and Placeholders
$values = array();
$place_holders = array();
$query = "";
$query_columns = "";
$query .= "INSERT INTO {$wp_table_name} (";
foreach($row_arrays as $count => $row_array)
{
foreach($row_array as $key => $value) {
if($count == 0) {
if($query_columns) {
$query_columns .= ",".$key."";
} else {
$query_columns .= "".$key."";
}
}
$values[] = $value;
if(is_numeric($value)) {
if(isset($place_holders[$count])) {
$place_holders[$count] .= ", '%d'";
} else {
$place_holders[$count] .= "( '%d'";
}
} else {
if(isset($place_holders[$count])) {
$place_holders[$count] .= ", '%s'";
} else {
$place_holders[$count] .= "( '%s'";
}
}
}
// mind closing the GAP
$place_holders[$count] .= ")";
}
$query .= " $query_columns ) VALUES ";
$query .= implode(', ', $place_holders);
if($wpdb->query($wpdb->prepare($query, $values))){
return true;
} else {
return false;
}
}
Source: https://github.com/mirzazeyrek/wp-multiple-insert
In addition to inserting multiple rows using $wpdb, if you ever need to update existing rows following snippet should be helpful.
This is updated snippet of what #philipp provided above.
$values = array();
// We're preparing each DB item on it's own. Makes the code cleaner.
foreach ( $items as $key => $value ) {
$values[] = $wpdb->prepare( "(%d,%d)", $key, $value );
}
$values = implode( ",\n", $values );
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES {$values} ON DUPLICATE KEY UPDATE `quantity` = VALUES(quantity)";
This is a bit late, but you could also do it like this.
global $wpdb;
$table_name = $wpdb->prefix . 'your_table';
foreach ($your_array as $key => $value) {
$result = $wpdb->insert(
$table_name,
array(
'colname_1' => $value[0],
'colname_2' => $value[1],
'colname_3' => $value[2],
)
);
}
if (!$result) {
print 'There was a error';
}
not very nice, but if you know what you are doing:
require_once('wp-load.php');
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
#mysql_select_db(DB_NAME) or die();
mysql_query("INSERT into TABLE ('column1', 'column2', 'column3') VALUES
('value1', 'value2', 'value3'),
('otherval1', 'otherval2', 'otherval3'),
('anotherval1', 'anotherval2', 'anotherval3)");
Related
Im current creating my own query builder now and Im stuck with PDO's prepared statement. Isn't it possible to loop the the PDO's BindParam. I did it using foreach() but it's not working it only on works on the last data that the loop executed.
$sql = "SELECT * FROM users WHERE id = :a OR fname = :b";
$array = array(":a"=>"10002345", "Josh");
$stmt = $conn->prepare($sql);
foreach($array as $key => $value ) {
$stmt->bindParam($key, $value);
}
$stmt->execute();
it only binds the last data executed by the loop.
It is better to use ? placeholders in a query and pass array of data to execute:
$sql = "SELECT * FROM users WHERE id = ? OR fname = ?";
$array = array("10002345", "Josh"); // you don't even need keys here
$stmt = $conn->prepare($sql);
$stmt->execute($array);
Only just stumbled across this, but just for future reference...
Firstly, I'll work on the assumption that your example was supposed to read $array = array(":a"=>"10002345", ":b"=>"Josh");, as there would be an issue even if your :b key was absent.
In this bit:
foreach($array as $key => $value ) {
$stmt->bindParam($key, $value);
}
You haven't 'passed by reference'. The $value should be amended to &$value
foreach($array as $key => &$value ) {
$stmt->bindParam($key, $value);
}
This is because the bindParam method signature requires the value to be a variable reference:
public function bindParam ($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null) {}
(note the & before $variable).
The end result of your original query (sans &) is that all :params would be set to the value that is in the last iteration of $value in your original loop.
So, the result of
$sql = "SELECT * FROM users WHERE id = :a OR fname = :b";
$array = array(":a"=>"10002345", ":b"=>"Josh");
$stmt = $conn->prepare($sql);
foreach($array as $key => $value ) {
$stmt->bindParam($key, $value);
}
$stmt->execute();
Would be SELECT * FROM users WHERE id = 'Josh' OR fname = 'Josh'
Using named parameters (:param) has advantages over positional params (?), so it's worth reserving that option for prepared statements, as opposed to the accepted answer of "it's better to use ? placeholders", which is not the case.
In my database abstraction layer I use the following utility functions:
/**
* getFieldList return the list with or without PK column
* #param bool $withID - true when including parameter
*/
static protected function getFieldList( $withID = false )
{
if( $withID )
$result = '`' . static::getTableName( ) . '`' .
'.`' . static::getPrimaryKeyName( ) . '`, ';
else
$result = '';
return $result .= '`' . static::getTableName( ) . '`.' .
'`' . implode( '`, `'.static::getTableName( ) . '`.`', static::getFieldNames( ) ) . '`';
}
/**
* getFieldPlaceholders -
* #return string - all PDO place holders prefixed :
*/
static protected function getFieldPlacholders( )
{
return ':' . implode( ',:', static::getFieldNames( ) );
}
/**
* getUpdateList - SQL updates section
* #return string
*/
static private function getUpdateList( )
{
$result = array( );
foreach( static::getFieldNames( ) as $field ) {
if( $field === static::getPrimaryKeyName() ) continue;
$result[] = '`' . $field . '`=:' . $field;
}
return implode( ',', $result );
}
/**
* Bind the fields to PDO placeholdes
* #param PDOStatement $stmt statement that the fields are bound to
* #return void
*/
protected function bindFields( $stmt )
{
foreach( array_keys($this->fields) as $field ) {
if( $field === static::getPrimaryKeyName() ) continue;
$stmt->bindParam( ':' . $field, $this->fields[$field] );
// echo $field . '->' . $this->fields[$field] . '<br>';
}
}
/**
* Bind the fields to the placeholders
* #param PDOStatement $stmt - that the fields are bind to
* #return void
*/
protected function bindColumns( $stmt, $withID = false )
{
if( $withID )
$stmt->bindColumn( static::getPrimaryKeyName(), $this->ID );
foreach( static::getFieldNames() as $fieldname )
{
$stmt->bindColumn( $fieldname, $this->fields[$fieldname] );
}
}
/**
* parseResultset
* Set the values of the select results, resets dirty (object is in sync)
* #param mixed[] $result - associative array
*/
protected function parseResultset( $result )
{
foreach( $result as $field=> $value ) {
if( $field === static::getPrimaryKeyName() )
$this->ID = $value;
$this->fields[$field] = $value;
}
$this->dirty = array();
}
I have a CodeIgniter/PHP Model and I want to insert some data into the database.
However, I have this set in my 'raw' SQL query:
ON DUPLICATE KEY UPDATE duplicate=duplicate+1
I am using CodeIgniter and am converting all my previous in-controller SQL queries to ActiveRecord. Is there any way to do this from within the ActiveRecord-based model?
Thanks!
Jack
You can add the "ON DUPLICATE" statement without modifying any core files.
$sql = $this->db->insert_string('table', $data) . ' ON DUPLICATE KEY UPDATE duplicate=LAST_INSERT_ID(duplicate)';
$this->db->query($sql);
$id = $this->db->insert_id();
I hope it's gonna help someone.
The below process work for me in Codeigniter 3.0.6
public function updateOnDuplicate($table, $data ) {
if (empty($table) || empty($data)) return false;
$duplicate_data = array();
foreach($data AS $key => $value) {
$duplicate_data[] = sprintf("%s='%s'", $key, $value);
}
$sql = sprintf("%s ON DUPLICATE KEY UPDATE %s", $this->db->insert_string($table, $data), implode(',', $duplicate_data));
$this->db->query($sql);
return $this->db->insert_id();
}
Following the snippet linked by Pickett, I made a few modifications to:
1) Update it to use the new Query Builder (CI 3), formerly known as Active Record.
2) You can now pass an associative array (key => value) or an array of associative arrays. In the second form, it performs a multi-update.
I only tested it with mysqli, and it works well.
This piece of code goes in system/database/drivers/mysqli/mysqli_driver.php
function _duplicate_insert($table, $values)
{
$updatestr = array();
$keystr = array();
$valstr = array();
foreach($values as $key => $val)
{
$updatestr[] = $key." = ".$val;
$keystr[] = $key;
$valstr[] = $val;
}
$sql = "INSERT INTO ".$table." (".implode(', ',$keystr).") ";
$sql .= "VALUES (".implode(', ',$valstr).") ";
$sql .= "ON DUPLICATE KEY UPDATE ".implode(', ',$updatestr);
return $sql;
}
function _multi_duplicate_insert($table, $values)
{
$updatestr = array();
$keystr = array();
$valstr = null;
$entries = array();
$temp = array_keys($values);
$first = $values[$temp[0]];
foreach($first as $key => $val)
{
$updatestr[] = $key." = VALUES(".$key.")";
$keystr[] = $key;
}
foreach($values as $entry)
{
$valstr = array();
foreach($entry as $key => $val)
{
$valstr[] = $val;
}
$entries[] = '('.implode(', ', $valstr).')';
}
$sql = "INSERT INTO ".$table." (".implode(', ',$keystr).") ";
$sql .= "VALUES ".implode(', ',$entries);
$sql .= "ON DUPLICATE KEY UPDATE ".implode(', ',$updatestr);
return $sql;
}
And this goes into the /system/database/DB_query_builder.php file:
function on_duplicate($table = '', $set = NULL )
{
if ( ! is_null($set))
{
$this->set($set);
}
if (count($this->qb_set) == 0)
{
if ($this->db_debug)
{
return $this->display_error('db_must_use_set');
}
return FALSE;
}
if ($table == '')
{
if ( ! isset($this->qb_from[0]))
{
if ($this->db_debug)
{
return $this->display_error('db_must_set_table');
}
return FALSE;
}
$table = $this->qb_from[0];
}
$is_multi = false;
foreach (array_keys($set) as $k => $v) {
if ($k === $v) {
$is_multi = true; //is not assoc
break;
}
}
if($is_multi)
{
$sql = $this->_multi_duplicate_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->qb_set );
}
else
{
$sql = $this->_duplicate_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $this->qb_set );
}
$this->_reset_write();
return $this->query($sql);
}
Then you can do this for a single row insert/update:
$this->db->on_duplicate('table', array('column1' => 'value', 'column2' => 'value'));
Or this for a multi insert/update:
$this->db->on_duplicate('table', array(
array('column1' => 'value', 'column2' => 'value'),
array('column1' => 'value', 'column2' => 'value')
));
You can tweak the active record function with minimal addition:
DB_driver.php add inside the class:
protected $OnlyReturnQuery = false;
public function onlyReturnQuery($return = true)
{
$this->OnlyReturnQuery = $return;
}
find function query( ...and add at the very beginning:
if ($this->OnlyReturnQuery) {
$this->OnlyReturnQuery = false;
return $sql;
}
and finally in DB_active_rec.php add function:
public function insert_or_update($table='', $data=array())
{
$this->onlyReturnQuery();
$this->set($data);
$insert = $this->insert($table);
$this->onlyReturnQuery();
$this->set($data);
$update = $this->update($table);
$update = preg_replace('/UPDATE.*?SET/',' ON DUPLICATE KEY UPDATE',$update);
return $this->query($insert.$update);
}
Now you can use it as:
$this->db->insert_or_update('table',array $data);
Pros:
uses all the active record validation
Cons:
it is not the best (the most proper) way of extending the function, because if you are planning to update these files, you will have to redo the procedure.
The link to the forum thread above is broken. I don't know of a better way than just using db->query for the call, if someone has a better solution, please post that.
$result = $this->CI->db->query(
"INSERT INTO tablename (id, name, duplicate) VALUES (1, 'Joe', 1) ".
"ON DUPLICATE KEY UPDATE duplicate=duplicate+1");
I hope this helps someone looking for a solution to this.
Below is a code snippet I use everytime for update on duplicates:
$sql = "insert into table_name (id, name) values(".$id.",'".$name."') on duplicate key update id=".$id.",name='".$name."'";
//Executing queries
$result = $this->db->query($sql, array($id, $name));
Note: column id must be primary or unique
Using $this->db->query() and parameters, this is how I do it. the first 4 parameters are for the insert part and the last three parameters are repeated for the on duplicate key update part.
$sql = "insert into application_committee ".
"(application_id, member1_id, member2_id, member3_id) values (?, ?, ?, ?)".
" on duplicate key update member1_id = ?, member2_id = ?, member3_id = ?";
$this->db->query($sql, array($appid, $member_1, $member_2, $member_3,
$member_1, $member_2, $member_3);
Simply done -
$updt_str = '';
foreach ($insert_array as $k => $v) {
$updt_str = $updt_str.' '.$k.' = '.$v.',';
}
$updt_str = substr_replace($updt_str,";", -1);
$this->db->query($this->db->insert_string('table_name', $insert_array).' ON DUPLICATE KEY UPDATE '.$updt_str);
I have an array that looks like this
$users = array(
array('name'=>'aaa','age'=>2),
array('name'=>'bbb','age'=>9),
array('name'=>'ccc','age'=>7)
);
I would like to create a function that will accept an array like above, creates a clause for a single query-multiple insert, prepares an array of variable that I can bind with PDO.
example output:
$clause = INSERT INTO tablename (`name`,`age`)
VALUES (:name_0,:age_0),(:name_1,:age_1),(:name_2,:age_2);
Then another set of array corresponding to the values above:
$params => Array
(
[name_0] => aaa
[age_0] => 2
[name_1] => bbb
[age_1] => 9
[name_2] => ccc
[age_2] => 7
);
So that the can execute it like so:
$prepared = $connection->prepare($clause);
$prepared->execute($params);
Is it possible to achieve this in a single function?
Yes that very possible, I did exactly the same thing for my custom query builder class:
function INSERT_MULTIPLE_QUERY($ARRS = array()){
$raw_cols = '(`';
// PREPARE THE COLUMNS
foreach($ARRS[0] as $key1 => $value):
$raw_cols .= $key1.'`,`';
endforeach;
$final_cols = rtrim($raw_cols,'`,`') . '`)';
$ctr1=0; $raw_vals='';
// PREPARE THE VALUES
foreach($ARRS as $ARR_VALUE):
$raw_vals .= '(';
foreach($ARR_VALUE as $key => $value): $raw_vals .= ':'.$key.'_'.$ctr1.','; endforeach;
$raw_vals = rtrim($raw_vals,',');
$raw_vals .= '),';
$ctr1++;
endforeach;
$final_vals = rtrim($raw_vals,',');
$ctr2 = 0; $param = array();
// PREPARE THE PARAMETERS
foreach($ARRS as $ARR_PARAM):
foreach($ARR_PARAM as $key_param => $value_param):$param[$key_param.'_'.$ctr2] = $value_param; endforeach;
$ctr2++;
endforeach;
// PREPARE THE CLAUSE
$clause = 'INSERT INTO tablename ' . $final_cols . ' VALUES ' . $final_vals;
// RETURN THE CLAUSE AND THE PARAMETERS
$return['clause'] = $clause;
$return['param'] = $param;
return $return;
}
Now to use this function:
$query = INSERT_MULTIPLE_QUERY($users);
// $users is your example array above
Then:
$prepared = $connection->prepare($query['clause']);
$prepared->execute($query['param']);
You can do it in a OOP style by creating a QueryBuilder and PDOStatementDecorator like below:
class QueryBuilder
{
const BUILD_TYPE_INSERT_MULTIPLE = 'INSERT_MULTIPLE';
protected $table;
protected $values;
protected $buildType;
public function __construct($table)
{
$this->table = $table;
}
public static function onTable($table)
{
return new self($table);
}
public function insertMultiple(Array $values = array())
{
$this->values = $values;
$this->buildType = self::BUILD_TYPE_INSERT_MULTIPLE;
return $this;
}
public function build()
{
switch ($this->buildType) {
case self::BUILD_TYPE_INSERT_MULTIPLE:
return $this->buildInsertMultiple();
}
}
protected function buildInsertMultiple()
{
$fields = array_keys($this->values[0]);
$query = "INSERT INTO {$this->table} (" . implode(',', $fields) . ") VALUES ";
$values = array();
for ($i = 0; $i < count($fields); $i++) {
$values[] = '(' . implode(', ', array_map(function($field) use ($i) {
return ':' . $field . $i;
}, $fields)) . ')';
}
$query .= implode(', ', $values);
return $query;
}
}
class PDOStatementDecorator
{
protected $pdoStatement;
public function __construct(PDOStatement $pdoStatement)
{
$this->pdoStatement = $pdoStatement;
}
public function executeMultiple(Array $bindsGroup = array())
{
$binds = array();
for ($i = 0; $i < count($bindsGroup); $i++) {
foreach ($bindsGroup[$i] as $key => $value) {
$binds[$key . $i] = $value;
}
}
return $this->execute($binds);
}
public function execute(Array $inputParemeters)
{
return $this->pdoStatement->execute($inputParemeters);
}
public function fetch($fetchStyle = null, $cursorOrientation = 'PDO::FETCH_ORI_NEXT', $cursorOffset = 0)
{
return $this->pdoStatement->fetch($fetchStyle, $cursorOrientation, $cursorOffset);
}
/**
* TODO
* Implement all public PDOStatement methods
*/
}
The query builder can be enhanced to be able to build queries for update/delete statements.
Now the usage would be very simple:
$users = array(
array('name' => 'aaa', 'age' => 2),
array('name' => 'bbb', 'age' => 9),
array('name' => 'ccc', 'age' => 7),
);
$query = QueryBuilder::onTable('users')->insertMultiple($users)->build();
$stmt = new PDOStatementDecorator($pdo->prepare($query));
$stmt->executeMultiple($users);
This function require Table Name, your original array, and an optional parameter that is used as default value, only if one field is not present in all array rows:
function buildQuery( $table, $array, $default='NULL' )
{
/* Retrieve complete field names list: */
$fields = array();
foreach( $array as $row ) $fields = array_merge( $fields, array_keys( $row ) );
$fields = array_unique( $fields );
/* Analize each array row, then update parameters and values chunks: */
$values = $params = array();
foreach( $array as $key => $row )
{
$line = array();
foreach( $fields as $field )
{
if( !isset( $row[$field] ) )
{ $line[] = $default; }
else
{
$line[] = ":{$field}_{$key}";
$params["{$field}_{$key}"] = $row[$field];
}
}
$values[] = '('.implode(',',$line).')';
}
/* Compone MySQL query: */
$clause = sprintf
(
"INSERT INTO `%s` (`%s`) VALUES %s;",
$table,
implode( '`,`', $fields ),
implode( ',', $values )
);
/* Return array[ clause, params ]: */
return compact( 'clause', 'params' );
}
Calling it in this way:
$query = buildQuery( 'mytable', $users );
$query will contain this:
Array
(
[clause] => INSERT INTO `mytable` (`name`,`age`) VALUES (:name_0,:age_0),(:name_1,:age_1),(:name_2,:age_2);
[params] => Array
(
[name_0] => aaa
[age_0] => 2
[name_1] => bbb
[age_1] => 9
[name_2] => ccc
[age_2] => 7
)
)
eval.in demo
I just started creating mysqli bind_param update function. My insert function works fine, but there i get error - Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables. I dont get where is the problem.
My array = Array ( [bday_month] => 9 [bday_day] => 7 [bday_year] => 2003 [id] => 2 )
public function update($table, $data) {
if (empty($table) || empty($data)) {
return false;
}
$array_slice = array_slice($data, 0, count($data)-1);
$fields = implode(' = ?, ', array_keys($array_slice)) . ' = ?';
$stmt = $this->db->prepare("UPDATE `{$table}` SET {$fields} WHERE `id` = ?");
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($data));
$stmt->execute();
}
Solved. I forget insert types.
i have this one worked for me you could see it
/**
* update
* #author Alaa M. Jaddou
* #param string $table A name of table to insert into
* #param string $data An associative array
* #param string $where the WHERE query part
*/
public function update($table, $data, $where)
{
ksort($data);
$fieldDetails = NULL;
foreach($data as $key=> $value) {
$fieldDetails .= "`$key`= ?,";
}
$fieldDetails = rtrim($fieldDetails, ',');
$sth = $this->prepare("UPDATE $table SET $fieldDetails WHERE $where");
$values = array();
foreach ($data as $key => $value) {
$values = implode(', ', $value);
}
$sth->bind_param($values);
return $sth->execute();
}
Hi so I have an insert statement which works well, but need to create a separate update function which uses array keys and array values, which would be quite like the insert function but updates.
I have this for my insert
$sql = "INSERT INTO $tablename (".implode(",", array_keys($DATA).")" . " DATA ('".implode("','",array_values($DATA))."')";
connect()->query($sql);
This is what I have for my update so far but am stuck with it,
<?php
function updatethis (array $id, array $values, $tablename)
{
$sql = "UPDATE $tablename SET (".implode(",", array_keys($DATA)).")" . " DATA ('".implode("','",array_values($DATA))."')";
dbconnect()->query($sql);
}
?>
Therefore I would like help on the update feature please .
So I am getting an error with the UPDATE syntax
This is the part i am struggling with, i cna give further explanation, but i must have put in the wrong syntax to update the database after i click edit on the index page it calls the function just the syntax is incorrect.
also its php to mySQL
index page for PHP updatee fucntion
{
$values = array();
$idValues = array($idColumn => $id);
foreach($_POST as $key => $value)
{
if(!empty($value) && ($value != "Submit"))
{
$values[$key] = $value;
}
}
$result = update($idValues, $values, $tableName);
}
Edit: Error I am getting
edit has not been successfull from below
if(isset($_POST['Submit']))
{
if($result>0)
{
echo 'Edit has been successful. Return to index page';
}
else
{
echo 'Edit has not been successful.';
}
}
My code
function updateAll(array $id, array $values, $tablename)
{
$sIDColumn = key($id);
$sIDValue = current($id);
$arrayValues = $values;
array_walk($values, function(&$value, $key){
$value = "{$key} = '{$value}'";
});
$sUpdate = implode(", ", array_values($values));
$sql = "UPDATE {$tablename} SET {$sUpdate} WHERE {$sIDColumn} = '{$sIDValue}'";
connect()->query($sql);
}
My aim: takes the input of the unique identifier of the row to be edited as an array of 1 then the value plus the name of the column representing the primary key, an array containing the values indexed by the column names as well as a string representing the table name useing array_keys and array_vaules like th insert but to update
You cannot UPDATE in the same way of INSERT. It should be like this :
$valueSets = array();
foreach($values as $key => $value) {
$valueSets[] = $key . " = '" . $value . "'";
}
$conditionSets = array();
foreach($id as $key => $value) {
$conditionSets[] = $key . " = '" . $value . "'";
}
$sql = "UPDATE $tablename SET ". join(",",$valueSets) . " WHERE " . join(" AND ", $conditionSets);
See details here http://dev.mysql.com/doc/refman/5.7/en/update.html
I believe the pattern you are using is incorrect?
UPDATE table SET (rows) DATA ('values');
I think updates look more like this:
UPDATE table SET row1 = 'value1', row2 = 'value2';
In which case, this may be closer to what you are looking for.
function updatethis(array $id, array $values, $tablename)
{
$sIDColumn = key($id);
$sIDValue = current($id);
$arrayValues = $values;
array_walk($values, function(&$value, $key){
$value = "{$key} = '{$value}'";
});
$sUpdate = implode(", ", array_values($values));
$sql = "UPDATE {$tablename} SET {$sUpdate} WHERE {$sIDColumn} = '{$sIDValue}'";
dbconnect()->query($sql);
}
Using it, I get this query:
$testArray = array(
"id" => 19,
"username" => "test"
);
updatethis(array("id" => 9), $testArray, "users");
UPDATE users SET id = '19', username = 'test' WHERE id = '9'
I hope this at least helps but when it comes to databases, I only know MySQL and it is possible you are using another language.
I think you can try something like this :
$champs : Array of fields to update
$valeurs : Array of value to update fields
$conditions : Array of conditions
protected function modify($table,$champs,$valeurs,$conditions){
$Requete = "UPDATE ".$table." SET ";
$nbChamps = count($champs);
$nbValeurs = count($valeurs);
if($nbChamps == $nbValeurs){
for($i = 0; $i < $nbChamps ; $i++){
if($i < ($nbChamps - 1)){
if(is_numeric($valeurs[$i]))
$Requete = $Requete.$champs[$i]." = ".$valeurs[$i].",";
else
$Requete = $Requete.$champs[$i]." = '".$valeurs[$i]."',";
}
else
if(is_numeric($valeurs[$i]))
$Requete = $Requete.$champs[$i]." = ".$valeurs[$i]." ";
else
$Requete = $Requete.$champs[$i]." = '".$valeurs[$i]."' ";
}
$Requete = $Requete.$this->genereConditions($conditions);
$this->db->query($Requete);
}
else
throw new Exception("Le nombre de champs n'est pas identique au nombre de valeurs", 1);
}
private function genereConditions($conditions){
$condition = "WHERE ";
for($i = 0 ; $i < count($conditions); $i++){
if($i < (count($conditions)) - 1)
$condition = $condition.$conditions[$i]." AND ";
else
$condition = $condition.$conditions[$i];
}
return $condition;
}