提问人:Brian Warshaw 提问时间:8/16/2008 最后编辑:DharmanBrian Warshaw 更新时间:9/25/2021 访问量:5934
变量参数/结果与预准备语句绑定
Variable parameter/result binding with prepared statements
问:
在我即将结束的一个项目中,我编写并实现了一个针对 PHP 的对象关系映射解决方案。在怀疑者和梦想家大声疾呼“到底是怎么回事?”之前,放松一下——我还没有找到一种方法来让后期的静态绑定起作用——我只是在尽我所能地解决它。
无论如何,我目前没有使用准备好的语句进行查询,因为我无法想出一种方法将可变数量的参数传递给 or 方法。bind_params()
bind_result()
你问,为什么我需要支持可变数量的参数?因为我的模型的超类(把我的解决方案想象成一个被黑客入侵的 PHP ActiveRecord wannabe)是定义查询的地方,所以 find() 方法,例如,不知道它需要绑定多少参数。
现在,我已经考虑过构建一个参数列表并将字符串传递给 eval(),但我不太喜欢这个解决方案——我宁愿实现我自己的安全检查并传递语句。
有没有人对如何完成这项工作有任何建议(或成功案例)?如果你能帮我解决第一个问题,也许我们可以解决绑定结果集的问题(我怀疑这会更困难,或者至少如果它涉及确定表结构的初始查询,则会更耗费资源)。
答:
在 PHP 中,您可以使用 call_user_func_array
将可变数量的参数传递给函数或方法。方法的一个示例如下:
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
该函数将被调用,数组中的每个成员都作为其自己的参数传递。
评论
bind_param
bindparams
mysqli
$stmt->bind_param()
$stmt->bindparams()
我不被允许编辑,但我相信代码
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
$stmt前面的引用不是必需的。由于 是对象,并且是该对象中的方法,因此引用不是必需的。它应该是:$stmt
bindparams
call_user_func_array(array($stmt, 'bindparams'), $array_of_params);
有关更多信息,请参阅有关回调函数的 PHP 手册。
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();
你必须确保 $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);
动态绑定参数的更现代方法是通过 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);
评论