I had a problem when making the insert function with bindParam or bindValue, always error like this:
what should be improved from my code :
<?php
function IUD($sql, $param = array()){
global $koneksi;
$stmt = $koneksi->prepare($sql);
foreach ($param as $key => $value) {
if(is_int($value)){
$stmt->bindParam("$key", $value, PDO::PARAM_INT);
}else{
$stmt->bindParam("$key", $value);
}
}
$ret = $stmt->execute();
}
$insert = IUD("INSERT INTO user (nama_lengkap,username,password,type_user,foto,tgl) VALUES(:nm,:user,:pass,:type,:foto,:tgl)", array(':nm'=>$nm,':user'=>$user,'pass:'=>$pass,':type'=>$type,':foto'=>$foto,'tgl'=>$tgl));
?>
You had a typo, that's all. You should have:
':tgl' => $tgl
In your query $params array.
Related
i had problem INSERT data to mysql using PHP OOP.
so, this is my code :
public function insert($setType, $setTable, $setRow, $setValues) {
$change = function($values) {
return "?";
};
$row = join(",", $setRow);
$done = join(",", array_map($change, $setValues));
$values[] = join(",", $setValues);
function SqlArrayReferenceValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) {
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
$insert = $this->connect->prepare("INSERT INTO $setTable ($row) VALUES ($done)");
$mergedValues = array_merge(array($setType), $values);
call_user_func_array(array($insert, "bind_param"), SqlArrayReferenceValues($mergedValues));
$insert->execute();
$insert->close();
return $insert;
}
if (empty($_SESSION['transaction'])) :
$idt = date("ymdhis");
$_SESSION['transaction'] = $idt;
endif;
$st = $_SESSION['transaction'];
if (isset($_SESSION['email'])) :
$se = $_SESSION['email'];
$user = $objMysql->query(array("*"), "user", "email = '$se'");
$dataUser = $objMysql->fetch($user);
$ide = $dataUser['id_user'];
else :
$ide = 0;
endif;
$currentLink = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$objMysql->insert("sis", "url", array("id_transaction", "id_user", "url"), array("$st", "$ide", "$currentLink"));
this is my mysql table :
id_transaction row - type varchar.
id_user row - type INT
url row - type text
i got 1 errors,
mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables in
what's wrong with my code?
FINAL SOLUTION BY MARTIN
public function SqlArrayReferenceValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) {
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
public function insert($setType, $setTable, $setRow, $setValues) {
$change = function($values) {
return "?";
};
$row = join(",", $setRow);
$done = join(",", array_map($change, $setValues));
$insert = $this->connect->prepare("INSERT INTO $setTable ($row) VALUES ($done)");
$params = $setValues;
$ww = array_merge(array($setType), $params);
call_user_func_array(array($insert, "bind_param"), $this->SqlArrayReferenceValues($ww));
$insert->execute();
$insert->close();
return $insert;
}
As correctly noted in comments, by Mark Baker and bub, you are passing a string value in the place of an array value.
What you have is an array of values you then turn into a string, before then trying to use them as an array. There is no need use join on the $values variable.
//$values = join(",", $setValues); // comment out this line,
call_user_func_array(array($insert, "bind_param"), array_unshift(array($setType), $setValues));
Here you use array_unshift to insert the array TYPES that you passed to the function, at the start of the array. This will now give you a correct array to insert into bind_param:
array("sis", $st, $side, $currentLink);
Problems with expected by reference:
There is an issue with the above that the MySQLi OOP code expects objects as references, so as well as the above- the values needs to be run through a separate process to give their "true" values to the call_user_func_array() function.
In your class/script add:
private function SqlArrayReferenceValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) {
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
This function takes the values and returns the correct value types to the call_user_array_function.
so:
$mergedValues = array_unshift($setValues, $setType);
call_user_func_array(array($insert, "bind_param"), $this->SqlArrayReferenceValues($mergedValues));
I got this code from somewhere on Stack Overflow and it's been very useful for years! This is the link: https://stackoverflow.com/a/16120923/3536236
Update 3:
How your code should look:
private function SqlArrayReferenceValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) {
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
public function insert($setType, $setTable, $setRow, $setValues) {
$change = function($values) {
return "?";
};
$row = join(",", $setRow);
$setValuesCopy = $setValues;
$done = join(",", array_map($change, $setValuesCopy));
$insert = $this->connect->prepare("INSERT INTO ".$setTable." (".$row.") VALUES (".$done.")");
$mergedValues = array_unshift($setValues, $setType);
//probably not needed but resetting array numerical indexing:
$mergedValues = array_values($mergedValues);
call_user_func_array(array($insert, "bind_param"), $this->SqlArrayReferenceValues($mergedValues));
$insert->execute();
$insert->close();
return $insert;
}
$currentLink = "http://".$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI]";
$objMysql->insert("sis", "url", array("id_transaction", "id_user", "url"), array($st, $ide, $currentLink));
i am sending $_POST['checkbox_name'] to function insert_to_table.
function insert_to_table($valid_array)
{
$data_array = array();
$this->load->model('get_data_model');
$updated_max_brand_id = $this->get_data_model->get_max_brand_id();
foreach ($valid_array as $key => $value) {
$data_array['bdc_brand_id'] = $updated_max_brand_id;
$data_array['bdc_cat_id'] = $value;
}
$this->db->insert('mart_brand_dealing_cat',$data_array);
}
the final mysql query should run as below
INSERT INTO `mart_brand_dealing_cat` (`bdc_brand_id`, `bdc_cat_id`) VALUES (11,43),(11,42);
11 - updated_max_brand_id;
42,43 are coming from already existed array $valid_array.
I am trying to insert multiple values at a time.How can i do it. i may wrong please guide and help me.
Your probably looking for something like $this->db->insert_batch();
So for example:
<?php
function insert_to_table($valid_array)
{
$this->load->model('get_data_model');
$brand_id = $this->get_data_model->get_max_brand_id();
$insert = array();
foreach ($valid_array as $key => $cat_id) {
$insert[] = array(
'bdc_brand_id' => $brand_id,
'bdc_cat_id' => $cat_id,
);
}
if (!empty($insert)) {
return $this->db->insert_batch('mart_brand_dealing_cat', $insert);
} else {
return false;
}
}
?>
This is driving me absolutely crazy, I've rewritten it several times and still no go. My insert function works perfectly fine. I have no idea what I'm overlooking, anything you could suggest that might help would be extremely appreciated.
function update($table, $data, $idName='id')
{
if(empty($data) || !is_array($data))
return false;
$columns = $values = array();
foreach($data as $key => $val)
$columns[] = "$key=:$key";
$columns = makeCSL($columns, false);
try {
$qStr = "UPDATE $table SET $columns WHERE $idName=:id";
echo $qStr;
$query = $this->dbHandle->prepare($qStr);
foreach($data as $key => $val)
$query->bindParam("':$key'", $val, PDO::PARAM_STR);
$query->execute();
} catch(PDOException $e) {
$this->errCode = $e->getCode();
$this->errInfo = $e->errorInfo[2];
}
}
You have several problems.
First, you shouldn't put quotes around the placeholder being bound. Second, you need to use bindValue, because bindParam binds to a reference, so everything will be bound to the value of $val from the last time through the loop. And third, you don't have a binding for :id.
So it should be:
foreach($data as $key => $val) {
if ($key != 'id') {
$columns[] = "$key=:$key";
}
}
...
foreach ($data as $key => $val) {
$query->bindValue(":$key", $val, PDO::PARAM_STR);
}
Got it working with the following code
function update($table, $data, $idName="id")
{
if(empty($data) || !is_array($data))
return false;
$columns = array();
foreach($data as $key => $val)
$columns[] = "$key=:$key";
$columns = makeCSL($columns, false);
try {
$query = $this->dbHandle->prepare("UPDATE $table SET $columns WHERE $idName=:id");
$query->execute($data);
} catch(PDOException $e) {
$this->errCode = $e->getCode();
$this->errInfo = $e->errorInfo[2];
}
}
In trying to create a simple PHP PDO update function that if the field is not found would insert it, I created this little snippet.
function updateorcreate($table,$name,$value){
global $sodb;
$pro = $sodb->prepare("UPDATE `$table` SET value = :value WHERE field = :name");
if(!$pro){
$pro = $sodb->prepare("INSERT INTO `$table` (field,value) VALUES (:name,:value)");
}
$pro->execute(array(':name'=>$name,':value'=>$value));
}
It does not detect though if the update function is going to work with if(!$pro); How would we make this one work.
You are assigning $pro to the prepare, not the execute statement.
Having said that, if you are using mysql you can use the insert... on duplicate key update syntax.
insert into $table (field, value) values (:name, :value) on duplicate key update value=:value2
You can't use the same bound param twice, but you can set two bound params to the same value.
Edit: This mysql syntax will only work where a key (primary or another unique) is present and would cause an insert to fail.
If it's mysql-only you could try INSERT INTO ... ON DUPLICATE KEY UPDATE
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
You will first need to execute it.
Apart from that, this is a dodgy way of doing this. It would be better to start a transaction, do a SELECT and then determine what to do (INSERT or UPDATE). Just checking whether the UPDATE query succeeded doesn't suffice, it succeeds when no row is found too.
try,
PDO::exec()
returns 1 if inserted.
2 if the row has been updated.
for prepared statements,
PDOStatement::execute()
You can try,
PDOStement::rowCount()
The following are PHP PDO helper functions for INSERT and UPDATE
INSERT function:
function basicInsertQuery($tableName,$values = array()){
/*
//
USAGE INSERT FUNCTÄ°ON
$values = [
"column" => $value,
];
$result = basicInsertQuery("bulk_operations",$values);
*/
try {
global $pdo;
foreach ($values as $field => $v)
$vals[] = ':' . $field;
$ins = implode(',', $vals);
$fields = implode(',', array_keys($values));
$sql = "INSERT INTO $tableName ($fields) VALUES ($vals)";
$rows = $pdo->prepare($sql);
foreach ($values as $k => $vl)
{
$rows->bindValue(':' . $k, $l);
}
$result = $rows->execute();
return $result;
} catch (\Throwable $th) {
return $th;
}
}
UPDATE function:
function basicUpdateQuery($tableName, $values = array(), $where = array()) {
/*
*USAGE UPDATE FUNCTÄ°ON
$valueArr = [ column => "value", ];
$whereArr = [ column => "value", ];
$result = basicUpdateQuery("bulk_operations",$valueArr, $whereArr);
*/
try {
global $pdo;
//set value
foreach ($values as $field => $v)
$ins[] = $field. '= :' . $field;
$ins = implode(',', $ins);
//where value
foreach ($where as $fieldw => $vw)
$inswhere[] = $fieldw. '= :' . $fieldw;
$inswhere = implode(' && ', $inswhere);
$sql = "UPDATE $tableName SET $ins WHERE $inswhere";
$rows = $pdo->prepare($sql);
foreach ($values as $f => $v){
$rows->bindValue(':' . $f, $v);
}
foreach ($where as $k => $l){
$rows->bindValue(':' . $k, $l);
}
$result = $rows->execute();
return $result;
} catch (\Throwable $th) {
return $th;
}
}
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 have a function to do a simple insert, but am trying to make the method more robust by passing an array.
And this is the array I pass into it:
$form_data = array(
"sort_order"=>$_POST['sort_order'],
"name"=>$_POST['page_name'],
"text"=>$_POST['page_text'],
"image"=>$_POST['page_image'],
"meta_desc"=>$_POST['meta_desc'],
"meta_kw"=>$_POST['meta_kw'],
"meta_author"=>$_POST['meta_author'],
"image_thumb"=>"NULL",
);
Here is the function code:
public function insert_data($array){
$keys = array();
$values = array();
foreach($array as $k => $v){
$keys[] = $k;
if(!empty($v)){
$values[] = $v;
} else {
$values[] = "NULL";
}
}
$stmt = self::$mysqli->stmt_init();
$query = "INSERT INTO `".DB_TABLE_PAGES."` (".implode(",",$keys).") VALUES (?,?,?,?,?,?,?,?)";
$stmt->prepare($query);
$stmt->bind_param('ssssssss',implode(",",$values));
//$stmt->execute();
}
But I get this error:
Number of elements in type definition string doesn't match number of bind variables.
I know what the problem is, but I don't understand how I can achieve it.
Try this:
public function insert_data($array){
$placeholders = array_fill(0, count($array), '?');
$keys = $values = array();
foreach($array as $k => $v) {
$keys[] = $k;
$values[] = !empty($v) ? $v : null;
}
$stmt = self::$mysqli->stmt_init();
$query = 'INSERT INTO `'.DB_TABLE_PAGES.'` '.
'('.implode(',', $keys).') VALUES '.
'('.implode(',', $placeholders).')';
$stmt->prepare($query);
call_user_func_array(
array($stmt, 'bind_param'),
array_merge(
array(str_repeat('s', count($values))),
$values
)
);
$stmt->execute();
}
Or better yet, use PDO instead:
public function insert_data($array){
$placeholders = array_fill(0, count($array), '?');
$keys = $values = array();
foreach($array as $k => $v){
$keys[] = $k;
$values[] = !empty($v) ? $v : null;
}
// assuming the PDO instance is $pdo
$query = 'INSERT INTO `'.DB_TABLE_PAGES.'` '.
'('.implode(',', $keys).') VALUES '.
'('.implode(',', $placeholders).')';
$stmt = $pdo->prepare($query);
$stmt->execute($values);
}
Note: I've used the null constant because the "NULL" string will be escaped as a string (not as a null value).
I found something a little more concise.
Disclaimer, this works only since PHP 5.6 using the unpacking (splat) operator:
public function genericQueryWithParams($query, $params, $types)
{
$sql = $this->db->prepare($query));
$sql->bind_param($types, ...$params);
$sql->execute();
return $sql->get_result();
}
Instead of bind_param (which in my mind is confusing at all times), just do:
$stmt->execute($values);
You can also get rid of your loop by using array_keys() and array_values()