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

use*_*136 18 php mysql pdo

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

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

$stmt->execute($array);
Run Code Online (Sandbox Code Playgroud)

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

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

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);
Run Code Online (Sandbox Code Playgroud)

我试图做两个但它不使用bindParams执行:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);
Run Code Online (Sandbox Code Playgroud)

它的方法是什么?

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

goa*_*oat 18

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

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

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

请参阅PDO MySQL:是否使用PDO :: ATTR_EMULATE_PREPARES?


egg*_*yal 8

如文档中所述PDOStatement::execute:

input_parameters

一个值数组,其元素与正在执行的SQL语句中的绑定参数一样多.所有值均视为PDO::PARAM_STR.

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

在您的情况下,MySQL正在尝试执行LIMIT具有字符串参数的子句.虽然它可以尝试使用其隐式类型转换来解决这个问题,因为它会在其他任何地方出现一个整数应该出现的字符串,但它根本不会打扰而是会跑掉.

因此,您需要告诉PDO这些特定参数是整数.因为即使PHP不知道什么类型的变量是,我认为做到这一点的唯一方法是直接绑定他们要么PDOStatement::bindParamPDOStatement::bindValue你正在做的(尽管它不是严格必要指定$data_type参数作为一个简单(int)的投在$variable给PHP的,否则无能类型系统足以与工作).

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

祝好运!