如何传递PDO参数数组但仍指定其类型?

时间:2012-05-03 18:40:00

标签: php mysql pdo

$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";

我还想像这样使用数组输入:

$stmt->execute($array);

否则我不能重复使用相同的方法来执行我的查询。

同时,:limit1和:limit2不起作用,除非它像这样输入:

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);

我尝试了两者,但它没有使用bindParams执行:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);

它的方法是什么?

我认为我可以扩展PDOStatement并添加一个新方法“bindLimit”或者其他东西,但我无法弄清楚PDO使用什么内部方法将参数绑定到变量。

3 个答案:

答案 0 :(得分:18)

如果您关闭PDO::ATTR_EMULATE_PREPARES的默认设置,那么它将起作用。我刚刚发现mysql默认启用该设置,这意味着你从未真正使用预处理语句,php在内部为你创建动态sql,为你引用值并替换占位符。雅,一个主要的重点。

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare($sql);
$stmt->execute(array(5)); //works!

由于性能原因,默认情况下会模拟准备。

另见PDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?

答案 1 :(得分:8)

正如PDOStatement::execute的文档中所述:

  

input_parameters

     
    

具有与正在执行的SQL语句中的绑定参数一样多的元素的值数组。所有值都被视为PDO::PARAM_STR

  

在大多数情况下,这完全没有被注意到,因为MySQL的implicit type conversion处理其余部分(但如果MySQL使用特别奇怪的连接字符集,它可能会导致一些不良行为,因为将数字字符串转换回数字值可能不会给出预期的结果。)

在您的情况下,MySQL正在尝试执行具有字符串参数的LIMIT子句。虽然它可以尝试使用其隐式类型转换来解决这个问题,因为它会在其他任何地方出现一个字符串,其中应该是一个整数,it simply doesn't bother并且会跑掉而不是哭。

因此,您需要告诉PDO这些特定参数是整数。因为即使PHP不知道它的变量是什么类型,我相信唯一的方法就是直接用PDOStatement::bindParamPDOStatement::bindValue绑定它们(尽管它不是< em>严格必须将$data_type参数指定为(int)的简单$variable强制转换,从而为PHP提供了足够无用的类型系统。

就PDO用于将参数绑定到变量的内部方法而言,请查看really_register_bound_param()(不出所料,不会暴露给PHP,因此您将在C中获得很多乐趣)。

祝你好运!

答案 2 :(得分:0)

为什么在非用户输入时绑定限制值?

$start = 0;
$limit = 20;
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
    LIMIT $start, $limit";

即使$start$limit来自用户输入,例如来自$_GET,您也可以使用is_int()测试该值。