15

请看下面我的代码。我正在尝试将一组参数绑定到我准备好的语句。我一直在网上四处寻找,可以看到我必须使用 call_user_func_array 但无法让它工作。我得到的错误是:“第一个参数应该是一个有效的回调,给出了'数组'”我可能是错的,但我假设第一个参数可以是一个数组,也许这个错误消息具有误导性。我认为问题在于我的阵列在某种程度上有问题。谁能看到我做错了什么?谢谢。

$type = array("s", "s");
$param = array("string1","anotherstring");

$stmt = $SQLConnection->prepare("INSERT INTO mytable (comp, addl) VALUES (?,?)");

$params = array_merge($type, $param);

call_user_func_array(array(&$stmt, 'bind_param'), $params);
$SQLConnection->execute();
4

7 回答 7

20

它必须是这样的:

//connect
$mysqli = new mysqli($host, $user, $password, $db_name);

//prepare
$stmt = $mysqli->prepare("SELECT * FROM the_table WHERE field1= ? AND Field2= ?");

//Binding parameters. Types: s = string, i = integer, d = double,  b = blob
$params= array("ss","string_1","string_2");

//now we need to add references
$tmp = array();
foreach($params as $key => $value) $tmp[$key] = &$params[$key];
// now us the new array
call_user_func_array(array($stmt, 'bind_param'), $tmp);

$stmt->execute();

/* Fetch result to array */
$res = $stmt->get_result();
while($row = $res->fetch_array(MYSQLI_ASSOC)) {
  $a_data[]=$row;
}
print_r($a_data);

$stmt->close();
于 2014-07-12T13:38:28.293 回答
12

PHP 5.6起,您不必再胡思乱想call_user_func_array()了。

代替:

$stmt->bind_param($param_types, $my_params_array);

您可以只使用splat 运算符,如下所示:

$stmt->bind_param($param_types, ...$my_params_array); // exact code

于 2018-06-04T13:55:44.977 回答
9

我不知道你为什么必须使用call_user_func_array,但那是另一回事。

在我看来,唯一可能出错的是您正在使用对该对象的引用。假设您使用的是 PHP 5.*,则没有必要:

call_user_func_array(array($stmt, 'bind_param'), $params);
于 2009-12-16T11:05:41.920 回答
1

如果您遇到错误,您应该尝试以下操作:

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

function refValues($arr){
    if (strnatcmp(phpversion(),'5.3') >= 0) {
        $refs = array();
        foreach($arr as $key => $value)
            $refs[$key] = &$arr[$key];
        return $refs;
    }
    return $arr;
}
于 2016-11-04T22:26:34.820 回答
1

无法就我自己的问题回答这个问题,因为它被标记为 dupe: here。但我认为我的最终解决方案(使用此问题中的答案)适用于我的用例,可能对某人有所帮助。

我的目标是获取一组已发布的 ID,并在NOT INMYSQL 语句中使用它们。假设发布了 5 个 ID 的数组。

  1. 计算张贴 ID 的数量以构建?占位符以进行NOT IN声明。Using$params_count = substr(str_repeat(',?', count($array_of_ids)), 1);给出的结果是:(?,?,?,?,?)在 SQL 语句中使用。

  2. 制作需要 ID 和类型等的函数is对我来说,它们都是这样,i所以我的函数更简单。返回看起来像这样的数组,$params= array("iiiii",1,2,3,4,5)其中第一个值是i's 的集合,后续值是 ID,具体取决于传递给函数的总 ID。

    function build_bind_params($values, $bind_type) {
        $s = substr(str_repeat($bind_type, count($values)), 0);
        $bind_array = array();
        $bind_array[] = $s;
        foreach($values as $value) {
            $bind_array[] = $value;
        }
        return $bind_array; 
    }
    

$params = build_bind_params($array_of_ids, "i");

  1. 然后使用foreach ($params as $key => $value) $tmp[$key] = &$params[$key];使新创建$params的格式正确以进行绑定。

  2. 然后使用call_user_func_array(array($stmt , 'bind_param') , $tmp);正确绑定数组。

  3. 然后执行$stmt

于 2017-12-15T21:15:40.613 回答
1

在将类型与值添加到 call_user_func_array() 之前,如果没有将类型与值集成在一起,上述大多数都不是解决方案。这个解决方案对我有用:

/* create a database connection */
$db = new mysqli($host, $user, $password, $db_name);

/* setup the sql, values, and types */
$sql="SELECT * FROM languages 
         WHERE language_code = ?
           AND charset = ?
         ORDER BY native_name";
$values = array($langCode, $charset);
$types = "ss";   

/* pass those variables to the execute() function defined below */
if ($rows = execute($sql, $values, $types))
{
   return $rows[0];
}

function execute($sql, $values='', $types='')
{
   /* prepare the sql before binding values and types */
   $stmt = $db->prepare($sql);

   /*combine the values and types into $inputArray */
   $inputArray[] = &$types;
   $j = count($values);
   for($i=0;$i<$j;$i++){
     $inputArray[] = &$values[$i];
   }
   /* add the combined values and types to call_user_func_array() for binding */
   call_user_func_array(array($stmt, 'bind_param'), $inputArray);
   $result = $stmt->execute();
   return $result;
}

以下是此示例所基于的完整描述的参考:http: //big.info/2015/08/php-use-call_user_func_array-for-variable-number-of-parameters-arrays-in-prepared-statements.html

于 2018-01-03T17:48:02.713 回答
0

为什么要调用 call_user_func_array(array($statement, 'bind_param'), $bind_arguments)?因为 $bind_arguments 是一个数组。无论您有多少参数,您都将拥有一个将语句绑定到其查询参数的函数。

好的代码示例...

    <?php
            # link
        $dblink = new mysqli('HOSTNAME','USERNAME','PASSWORD','DATABASENAME');

            # example data
        $statement = $dblink->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?");
        $recordvalues = ['John', 'H.', 'Smith', 25];
        $sqlbindstring = "sssi";    # String, String, String, Integer example

            # make the references
        $bind_arguments = [];
        $bind_arguments[] = $sqlbindstring;
        foreach ($recordvalues as $recordkey => $recordvalue)
        {
            $bind_arguments[] = & $recordvalues[$recordkey];    # bind to array ref, not to the temporary $recordvalue
        }

            # query the db
        call_user_func_array(array($statement, 'bind_param'), $bind_arguments);     # bind arguments
        $statement->execute();  # run statement
        $result = $statement->get_result(); # get results

            # get the results
        if($result) {
            while ($row = $result->fetch_assoc()) {
                print("\n\nMy row is...");
                print_r($row);
            }
        }
    ?>

错误代码示例...

    <?php

            # Same setup as above..

        $statement->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?");
        $statement->bind('John', 'H.", 'Smith', 25);

    ?>

在第一个示例中:您可以将尽可能多的或尽可能少的传递给要完成的绑定,以便在整个应用程序中仅在一行中调用 bind()。这可以很好地扩展。

在第二个示例中:您必须为数据库中每个可能的记录的每个可能的插入组编写一个 bind() 语句。这很难扩展。

于 2016-02-21T21:38:56.543 回答