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
andbind_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
Calling Function Inside Preg_Replace Thats Inside a Function
How to Read Gzip-Ed Response from Stackoverflow API in PHP
Using PHP to Execute Multiple MySQL Queries
PHP Variable Inside Echo 'HTML Code'
How to Create a Custom Admin Page in Opencart
How to Switch from Post to Get in PHP Curl
PHP - Get Numeric Index of Associative Array
Calling Stored Procedure with Out Parameter Using Pdo
How to Count Query Result Rows
Syntax Error While Defining an Array as a Property of a Class
Ip Address Storing in MySQL Database Using PHP
Insert Current Date in Datetime Format MySQL
Enabling Postgresql Support in PHP on MAC Os X
Integrating Mailjet API V3 Wrapper as Codeigniter Library
Concatenation with Addition in It Doesn't Work as Expected
List and Download Clicked File from Ftp
How to Add a Class to Every Nth Item in a PHP Loop (Wordpress)