Mysqli Binding Params Using Call_User_Func_Array

MySQLI binding params using call_user_func_array

I wouldn't know why you have to use call_user_func_array, but that's another story.

The only thing that could be wrong in my eyes is that you are using a reference to the object. Assuming you're using PHP 5.*, that is not necessary:

call_user_func_array(array($stmt, 'bind_param'), $params);

call_user_func_array doesn't work with bind_param when passing array already in variable

If course it would be nice to know what kind of a query is involved, but in any event the following code works:

<?php
error_reporting(E_ALL);
$id=5;
$code = 'GR';
$country='Greece';

$mysqli = new mysqli("localhost", "root", "", "exp");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " .

$mysqli->connect_error;
}
echo $mysqli->host_info . "\n";

if (!($stmt = $mysqli->prepare("INSERT INTO countries VALUES (?,?,?)"))) {
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

//$stmt->bind_param('iss', $id, $code, $country);

$params = array('iss',$id,$code,$country);
$tmp = array();
foreach($params as $key => $value) $tmp[$key] = &$params[$key];

call_user_func_array( array($stmt, 'bind_param'), $tmp);

if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}

The code only works with my software when the $params array includes the letters specifying the type of data. Also the params themselves need to be references and not values. Note: I did borrow the code to turn values into references from this member of Stackoverflow.

call bind_param using call_user_func_array mysqli prepared statement

@Bill_Karwin commented this is a duplicate. I found the solution in that answer. Below is my function (I had to make the values of the parameters be references):

public function executePreparedStatement($query, $paramString = ''){
$stmt = $this->db->prepare($query);
if (func_num_args() > 2){
$parameters = func_get_args();
array_shift($parameters); // remove the query from the list
// Array needs to be bound by reference
foreach ($parameters as $key=>&$value) {
$parameters[$key] = &$value;
}
call_user_func_array(array($stmt, "bind_param"), $parameters);
}
$stmt->execute();
$this->result = $stmt->get_result();
$stmt->close();
}

MySQLI bind params using call_user_func_array not working

Try putting references into the array instead of values (notice the ampersands):

$params[] = &$param_type;
for($i = 0; $i < $n; $i++) {
$params[] = &$array_param[$i];
}

PHP Using call_user_func_array to bind_param

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));

php5.3 - mysqli_stmt:bind_params with call_user_func_array warnings

I found the answer to my problem in a user note by fabio at kidopi dot com dot br3 years ago on the PHP manual page of mysqli_stmt::bind_param() (slightly modified):

I used to have problems with call_user_func_array and bind_param after migrating to php 5.3.

The cause is that 5.3 requires array values as reference while 5.2 worked with real values (but also with references). So I created a secondary helper function to help me with this:

function refValues($arr)
{
$refs = array();

foreach ($arr as $key => $value)
{
$refs[$key] = &$arr[$key];
}

return $refs;
}

and changed my previous function from:

call_user_func_array(array($this->stmt, "bind_param"), $this->values); 

to:

call_user_func_array(array($this->stmt, "bind_param"), refValues($this->values)); 

This way my db functions keep working in PHP 5.2/5.3 servers.

call_user_func_array() - Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement

You can't quote the placeholder, that makes it the literal value and not a placeholder. Move the time into the binding and leave the placeholders on their own.

e.g.

where thedateandtime between ? and ?

then in the bind

($date . ' 00:00:00')

You also can't bind columns so the order by should be altered. Use a whitelist to compare the values before passing it into the query.

How to call mysqli_stmt with call_user_func_array?

The function that has been suggested to you needs to accept $params via reference as well. Here's a slightly updated version:

function refValues(&$arr)
{
//Reference is required for PHP 5.3+
if (strnatcmp(phpversion(),'5.3') >= 0)
{
$refs = array();
foreach(array_keys($arr) as $key)
{
$refs[$key] = &$arr[$key];
}
return $refs;
}

return $arr;
}


Related Topics



Leave a reply



Submit