-1

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,

  1. 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;     
    }
Ching Ching
  • 217
  • 1
  • 5
  • 15

1 Answers1

2

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));
Community
  • 1
  • 1
Martin
  • 22,212
  • 11
  • 70
  • 132
  • this problem occure : Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value given in – Ching Ching Oct 07 '15 at 12:01
  • thank you very much Mr. Martin for answering my question, i dont know this method still occuring problem , Warning mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables in – Ching Ching Oct 07 '15 at 12:13
  • you can try sticking in `$mergedValues = array_values($mergedValues);` just before `call_user_func_array` in order to correctly reindex the array, also please can you update your question with some code output to work, what is the `print_r` or var_dump of `$insert?` and of `$mergedValues` ? – Martin Oct 07 '15 at 12:19
  • I have found other serious issues with your code, @ChingChing so have updated my answer. Please use my updated answer. – Martin Oct 07 '15 at 12:25
  • Fatal error: Only variables can be passed by reference in – Ching Ching Oct 07 '15 at 12:32
  • which version of PHP are you using? – Martin Oct 07 '15 at 12:35
  • i'm using PHP version 5.6.3 – Ching Ching Oct 07 '15 at 12:38
  • I have written a complete solution at the bottom of my answer, please check that yours is the same, and see if you can identify where the passed by reference occurred? @ChingChing – Martin Oct 07 '15 at 12:42
  • @ChingChing updated I had a syntax error on `array_unshift`. corrected now – Martin Oct 07 '15 at 12:46
  • yeah, it's not showing Fatal error anymore, 1. array_values() expects parameter 1 to be array, integer given in 2. Invalid argument supplied for foreach() in 3. Wrong parameter count for mysqli_stmt::bind_param() in – Ching Ching Oct 07 '15 at 12:51
  • when you apply your `array_map` you should apply it to a copy (`$setValuesCopy`) of $setValues. I *think* that the array_map is changing the subject array. – Martin Oct 07 '15 at 13:33
  • oh my god, finally it's working right now, i will post it on my questions, it's all because Mr. Martin. Oh man! YOU DA REAL MVP!! god bless you! – Ching Ching Oct 07 '15 at 13:47
  • Glad we finally got it sorted, @ChingChing , feel free to +1 my answer too ;-) – Martin Oct 07 '15 at 13:48