PHP MySQL PDO Update not working - php

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];
}
}

Related

Wrong parameter count for bind_param in custom mysqli class

Trying to generate a custom mysqli class / wrapper with $this->_mysqli as a mysqli instance:
// Query string generator
private function gen_query($type, $data, $table){
switch ($type) {
case 'ins':
$query = "INSERT INTO " .$table .' ';
$query .= implode_key($opr= ', ', $data);
$query .= " VALUES " . value($data);
break;
case 'select':
// yet to generate
default:
$query ='';
break;
}
return $query;
}
// Generates bind parameters
private function gen_param($data){
$_param = "'";
foreach ($data as $v) {
$_param .= $this->detect_type($v);
}
$_param .= "', ";
foreach ($data as $k=>$v) {
if($v == end($data)) {
$_param .="$$k";
continue;
}
$_param .= "$$k, ";
}
return $_param;
}
public function insert( $table, $data ){
$table = $this->_prefix . $table;
$table = $this->escape($table);
$query = $this->gen_query('ins', $data, $table);
$stmt = $this->_mysqli->prepare($query);
foreach ($data as $key => $value) {
$$key = $value;
}
$test = $this->gen_param($data);
if(!$stmt->bind_param($test)) {
echo $this->_mysqli->error;
}
if($stmt->execute()){
print 'Success!'.'<br />';
} else {
die('Error : ('. $this->_mysqli->errno .') '. $this->_mysqli->error);
}
}
So when user inputs
$data = [ 'first_name' => 'foo', 'last_name' => 'bar', 'another_field' => 'blah'];
$db->insert('t1', $data);
I get this error:
Warning: Wrong parameter count for mysqli_stmt::bind_param() in path\to\class-db.php on line 138
This is line 138: if(!$stmt->bind_param($test))
Not sure why the question was downvoted. Anyways, I got this fixed by referring: this repo.
We'll need to get rid of gen_param, use an array instead and call using a callback function to get the parameter values right and refer the values.
The code is now:
public function insert( $table, $data ){
$table = $this->_prefix . $table;
$table = $this->escape($table);
$this->esc_sql_arr($data);
$query = $this->gen_query('ins', $data, $table);
$stmt = $this->_mysqli->prepare($query);
$this->_bind_param($data);
call_user_func_array(array($stmt, 'bind_param'),$this->return_ref($this->bind_arr));
if($stmt->execute()){
echo "Success!";
}else{
die('Error : ('. $this->_mysqli->errno .') '. $this->_mysqli->error);
}
$this->reset();
}
private function _bind_param($data){
foreach($data as $key=>$value) {
$this->_bind_values($value);
}
}
private function _bind_values($value) {
$this->bind_arr[0] .= $this->detect_type($value);
array_push($this->bind_arr, $value);
}
protected function return_ref(array &$arr)
{
//Reference in the function arguments are required for HHVM to work
//https://github.com/facebook/hhvm/issues/5155
//Referenced data array is required by mysqli since PHP 5.3+
if (strnatcmp(phpversion(), '5.3') >= 0) {
$refs = array();
foreach ($arr as $key => $value) {
$refs[$key] = & $arr[$key];
}
return $refs;
}
return $arr;
}
The code is nowhere near complete, but this got me started.

Function for PDO preapred stament not work and get error

I make 2 function with same use to take over PDO Preapred Statement, but both of not work .
Function 1 :
function doSave($array, $table) {
if (count($array) == 0) {
throw new Exception('Array cant be empty');
} else {
global $connect;
//prepare the query first
$prepare_1 = 'INSERT INTO' . ' ' . $table . ' '; //start preparing
$columns = array();
foreach ($array as $key => $value) {
$columns[] = ':' . $key; //gets all columns and add commas
}
foreach ($array as $key => $value) {
$keye[] = $key; //gets all columns and add commas
}
$keyes = implode(', ', $keye);
$column = implode(', ', $columns);
//now you can combine everything and prepare
$stmt99 = $connect->prepare($prepare_1 .'('.$keyes.')'. ' VALUES (' . $column . ')');
//remember to add the values. also test this section as its not tested
foreach ($array as $key => $value) {
$test[] = "':" . $key ."' => ". $value;
}
$tests = implode(', ', $test);
$stmt99->execute($tests);
}
}
When i insert the data i got no error and no data get insert to my database
Function 2 :
function doSave($array, $table) {
if (count($array) == 0) {
throw new Exception('Array cant be empty');
} else {
global $connect;
//prepare the query first
$prepare_1 = 'INSERT INTO' . ' ' . $table . ' '; //start preparing
$columns = array();
foreach ($array as $key => $value) {
$columns[] = ':' . $key; //gets all columns and add commas
}
foreach ($array as $key => $value) {
$keye[] = $key; //gets all columns and add commas
}
$keyes = implode(', ', $keye);
$column = implode(', ', $columns);
//now you can combine everything and prepare
$stmt99 = $connect->prepare($prepare_1 .'('.$keyes.')'. ' VALUES (' . $column . ')');
//remember to add the values. also test this section as its not tested
foreach ($array as $key => $value) {
$test[] = '$stmt99->bindparam('.'":' . $key .'",'. $value.'); ';
}
$tests = implode(' ', $test);
$tests;
$stmt99->execute();
}
}
i got error when use this function :
SQLSTATE[HY093]: Invalid parameter number: no parameters were bound
This How i use the function :
$array = array('categoryName' => $categoryName, 'categorySort' => $categorySort);
doSave($array, 'category');
This the source of the array :
if (!empty($_POST["categoryName"])) {
$categoryName = ($_POST["categoryName"]);
if (!preg_match("/^[a-zA-Z ]*$/",$categoryName)) {
$errMsg = "<div class='alert alert-danger text-center'><strong>Hanya boleh huruf.</strong></div>";
}
}
if ($_POST["categorySort"] == $check['categorySort']) {
$errMsg = "<div class='alert alert-danger text-center'><strong>Urutan sudah digunakan.</strong></div>";
}else{
$categorySort = ($_POST["categorySort"]);
if (!is_numeric($_POST['categorySort'])) {
$errMsg = "<div class='alert alert-danger text-center'><strong>Hanya boleh angka.</strong></div>";
}
}
What possibly go wrong from this 2 function both function for same use. Function 1 (named param) Function 2 (bindparam) ?
The following is not fully tested but displayed what I expected when I tested it using echo statements.
You should check the return value of prepare before attempting to execute the statement because it will return false if the statement failed to be prepared correctly.
function doSave( $array, $table ) {
try{
/* if you throw exceptions you should catch them!! */
if( empty( $array ) )throw new Exception('Array cant be empty');
if( empty( $table ) )throw new Exception('Table name cannot be empty');
global $connect;
/* placeholder variables */
$prepare = $columns = $values = array();
$result = false;
$table = preg_replace("#[',\.]#",'',$table);// whatever chars deemed appropriate to replace
$prepare[]="insert into `{$table}` ";
/* iterate through source array */
foreach( $array as $key => $value ) {
$columns[] = $key;
$values[ $key ] = $value;
}
$strcolumns = implode('`,`',$columns);
$strplaceholders = ':'.implode(', :',$columns);
/* append columns and placeholders */
$prepare[]="( `$strcolumns` ) values ( $strplaceholders );";
/* finalise sql statement */
$sql=implode('',$prepare);
$stmt = $connect->prepare( $sql );
if( $stmt ){
/* bind the params */
foreach( $values as $key => $value ) $stmt->bindParam( ':'.$key, $value );
/* execute the statement */
$result = $stmt->execute();
} else {
throw new Exception('Error preparing sql statement');
}
return $result;
}catch( Exception $e ){
exit( $e->getMessage() );
}
}
The assumption I made for the code was an input array like this
$t='mytable';
$a=array(
'id' => '303',
'name' => 'bob',
'size' => 'small',
'weight'=> 'heavy'
);
NOTE:
You have two functions both with the same name. How is PHP meant to know the which function you're calling?
Function 2:
foreach ($array as $key => $value) {
$test[] = '$stmt99->bindparam('.'":' . $key .'",'. $value.'); ';
}
Because you encased this in [single] quotes, this value is no longer an object method call but is just a string. This means that when you then implode this array all you're making is a longer string.
Also, because you're using single quotes, PHP will not recognise the value $stmt99 as being a PHP object reference, instead taking it literally as dollar sign, s character, t character, m character, etc....
So PDO has no values to bind into the SQL given.
Fix:
foreach ($array as $key => $value) {
$stmt99->bindparam(":" . $key , $value);
}
unset($key,$value); // always tidy up after foreach loops.
A better fix can be found exampled here

php update to mysql with array not updating

I have a function that should be updating a row, no errors what so ever in the logs. From what I see it should be working. I took the function from a update user function and tried to mimic it for the new feature.
Here is the data array posting to it.
$data = array('id' => $vid, 'name' => $vname, 'logo' => $vlogo, 'info' => $vinfo, 'site' => $vsite, 'est' => $vest);
The post works, I am doing a dump on the updatecompany page. So they do get set. I think it may be with the function. Any insight would be wonderful!
public static function updateCompany($toUpdate = array(), $company = null){
self::construct();
if( is_array($toUpdate) && !isset($toUpdate['id']) ){
if($company == null){
echo "No company ID set!";
}
$columns = "";
foreach($toUpdate as $k => $v){
$columns .= "`$k` = :$k, ";
}
$sql = self::$dbh->prepare("UPDATE companys SET {$columns} WHERE `id` = :id");
$sql->bindValue(":id", $company);
foreach($toUpdate as $key => $value){
$value = htmlspecialchars($value);
$sql->bindValue(":$key", $value);
}
$sql->execute();
}else{
return false;
}
}
$vid = $_POST["idnum"];
$vname = $_POST["name"];
$vlogo = $_POST["logo"];
$vinfo = $_POST["info"];
$vsite = $_POST["site"];
$vest = $_POST["est"];
I would maybe try using the bind array into your execute() method since you are just binding the values (I assume this is PDO). Another feature is to use an array to assemble the column portions and implode at the time of use.
public static function updateCompany($toUpdate = array(), $company = null)
{
# Also this may supposed to be: self::__construct(); ?? Notice the "__" before "construct"
self::construct();
if(is_array($toUpdate) && !isset($toUpdate['id'])) {
if(empty($company)){
# Throw exception, catch it in a parent wrapper
throw new \Exception("No company ID set!");
# Stop, no sense in continuing if an important part is missing
return;
}
foreach($toUpdate as $k => $v){
$bKey = ":{$k}";
# I would create a bind array here
$bind[$bKey] = $value;
# I generally save to an array here to implode later
$columns[] = "`{$k}` = {$bKey}";
}
# Add the id here
$bind[":id"] = $company;
# I would use a try here for troubleshooting PDO errors
try {
# Create sql with imploded columns
$sql = self::$dbh->prepare("UPDATE companys SET ".implode(",",$columns)." WHERE `id` = :id");
# Throw the bind array into the execute here
$sql->execute($bind);
}
catch(\PDOException $e) {
# I would only die here to see if there are any errors for troubleshooting purposes
die($e->getMessage());
}
} else {
return false;
}
}
Your update SQL could not work because you have comma in update value set.
See, you attached comma without any consideration:
$columns = "";
foreach($toUpdate as $k => $v){
$columns .= "`$k` = :$k, ";
}
Then the final SQL will look something like this:
UPDATE companys SET `name`=:name, `logo`=:logo, WHERE `id`=:id
Do you notice the comma just before WHERE? it should not be there!
So you should update the code like following:
$columns = "";
foreach($toUpdate as $k => $v){
if ($columns != "") $columns .= ",";
$columns .= "`$k` = :$k ";
}
This should be working.
or to no need to be aware of last comma try this:
$columns = array();
foreach($toUpdate as $k => $v){
$columns[] = "`$k` = :$k";
}
$sql = self::$dbh->prepare("UPDATE `companys` SET ".implode(',', $columns)." WHERE `id` = :id");

How To Create Function Insert In PHP PDO

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.

codeigniter: alteration of PHP array

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;
}
}
?>

Categories