PHP + MYSQLI:使用预准备语句的变量参数/结果绑定

时间:2008-08-15 19:50:53

标签: php mysql orm mysqli

在我即将结束的项目中,我已经为PHP编写并实现了一个对象关系映射解决方案。在怀疑者和梦想家喊出“怎么样?”之前,放松一下 - 我还没有办法让后期的静态绑定工作 - 我只是以最好的方式解决它。

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

为什么我需要支持可变数量的参数?因为我的模型的超类(将我的解决方案想象为hack-up-PHP ActiveRecord wannabe)是定义查询的地方,所以find()方法例如不知道绑定需要多少参数

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

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

5 个答案:

答案 0 :(得分:13)

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

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

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

答案 1 :(得分:2)

您必须确保$ 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); 

答案 2 :(得分:1)

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

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

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

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

有关详细信息,请参阅Callback Functions上的PHP手册。“

答案 3 :(得分:0)

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

假设:

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

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

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

答案 4 :(得分:0)

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