变量参数/结果与预准备语句绑定

Variable parameter/result binding with prepared statements

提问人:Brian Warshaw 提问时间:8/16/2008 最后编辑:DharmanBrian Warshaw 更新时间:9/25/2021 访问量:5934

问:

在我即将结束的一个项目中,我编写并实现了一个针对 PHP 的对象关系映射解决方案。在怀疑者和梦想家大声疾呼“到底是怎么回事?”之前,放松一下——我还没有找到一种方法来让后期的静态绑定起作用——我只是在尽我所能地解决它。

无论如何,我目前没有使用准备好的语句进行查询,因为我无法想出一种方法将可变数量的参数传递给 or 方法。bind_params()bind_result()

你问,为什么我需要支持可变数量的参数?因为我的模型的超类(把我的解决方案想象成一个被黑客入侵的 PHP ActiveRecord wannabe)是定义查询的地方,所以 find() 方法,例如,不知道它需要绑定多少参数。

现在,我已经考虑过构建一个参数列表并将字符串传递给 eval(),但我不太喜欢这个解决方案——我宁愿实现我自己的安全检查并传递语句。

有没有人对如何完成这项工作有任何建议(或成功案例)?如果你能帮我解决第一个问题,也许我们可以解决绑定结果集的问题(我怀疑这会更困难,或者至少如果它涉及确定表结构的初始查询,则会更耗费资源)。

php mysql mysqli

评论


答:

12赞 John Downey 8/16/2008 #1

在 PHP 中,您可以使用 call_user_func_array 将可变数量的参数传递给函数或方法。方法的一个示例如下:

call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);

该函数将被调用,数组中的每个成员都作为其自己的参数传递。

评论

0赞 Dani Sancas 1/3/2014
我认为函数名称应该是 .至少在我的版本中,我使用它打字,而不是.干杯!bind_parambindparamsmysqli$stmt->bind_param()$stmt->bindparams()
0赞 Steven Oxley 9/17/2008 #2

我不被允许编辑,但我相信代码

call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);

$stmt前面的引用不是必需的。由于 是对象,并且是该对象中的方法,因此引用不是必需的。它应该是:$stmtbindparams

call_user_func_array(array($stmt, 'bindparams'), $array_of_params);

有关更多信息,请参阅有关回调函数的 PHP 手册。

0赞 jsleuth 4/5/2010 #3
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);

在我的环境中对我不起作用,但这个答案让我走上了正确的轨道。实际有效的是:

$sitesql = '';
$array_of_params = array();
foreach($_POST['multiselect'] as $value){
    if($sitesql!=''){
        $sitesql .= "OR siteID=? ";
        $array_of_params[0] .= 'i';
        $array_of_params[] = $value;
    }else{
        $sitesql = " siteID=? ";
        $array_of_params[0] .= 'i';
        $array_of_params[] = $value;
    }
}

$stmt = $linki->prepare("SELECT IFNULL(SUM(hours),0) FROM table WHERE ".$sitesql." AND week!='0000-00-00'");
call_user_func_array(array(&$stmt, 'bind_param'), $array_of_params);
$stmt->execute();
1赞 zhikharev 8/30/2011 #4

你必须确保 $array_of_params 是变量链接的数组,而不是值本身。应该是:

$array_of_params[0] = &$param_string; //link to variable that stores types

然后。。。

$param_string .= "i";
$user_id_var = $_GET['user_id'];//
$array_of_params[] = &$user_id_var; //link to variable that stores value

否则(如果它是值数组),你会得到:

PHP 警告:参数 2 到 mysqli_stmt::bind_param() 应作为参考


再举一个例子:

$bind_names[] = implode($types); //putting types of parameters in a string
for ($i = 0; $i < count($params); $i++)
{
   $bind_name = 'bind'.$i; //generate a name for variable bind1, bind2, bind3...
   $$bind_name = $params[$i]; //create a variable with this name and put value in it
   $bind_names[] = & $$bind_name; //put a link to this variable in array
}

和 BOOOOOM:

call_user_func_array( array ($stmt, 'bind_param'), $bind_names); 
4赞 mickmackusa 10/13/2019 #5

动态绑定参数的更现代方法是通过 splat/spread 运算符 ()。...

若:

  • 您有一个非空值数组要绑定到您的查询,并且
  • 在查询的上下文中,您的数组值被适当地处理为字符串类型值,并且
  • 您的输入数组称为$values

PHP5.6 及更高版本的代码:

$stmt->bind_param(str_repeat('s', count($values)), ...$values);

事实上,如果你愿意,所有输入到的参数都可以用 splat/spread 运算符解压缩——数据类型字符串只需要是数组的第一个元素。bind_param()

array_unshift($values, str_repeat('s', count($values)));
$stmt->bind_param(...$values);