31

我想知道bindParam()(或bindValue())中的数据类型声明用于...

我的意思是,我认为如果我定义一个整数参数 ( PDO::PARAM_INT),则该参数必须转换为整数,例如

$delete->bindParam(1, $kill, PDO::PARAM_INT);
// should work like
$delete->bindParam(1, (int)$kill);

或者如果参数不是声明的类型,至少会抛出一个错误。但这种情况并非如此。

谷歌搜索,我在 php.net 存档中发现:

大家好,

我目前正在研究 PDO。正好在 bindParam() 函数上。第三个参数 data_type 似乎是在这里强制值的类型?但是当我尝试时:

$sql = "INSERT INTO produit (idproduit, nom, marque) VALUES (NULL, :nom, :marque)";
$stmt = $dbh->prepare($sql);
$nom = 'Testarossa'; $marque = 'Ferrari' ;
$stmt->BindValue(':marque',$marque) ;
$stmt->BindParam(':nom',$nom,PDO::PARAM_INT) ;

$stmt->execute(); $nom = '250 GTO' ;
$stmt->execute(); ?>

我期待在我的数据库中出现 PHP 错误或整数。但在我的数据库中,我有:

22 Testarossa 法拉利 23 250 GTO 法拉利

这意味着如果我有第三个参数它没有改变。或者也许我错过了什么。有人可以告诉我更多吗?或者有人可以告诉我在哪里可以找到有关它的信息。

问候,

赛勒斯

这正是我的情况。我的想法哪里错了?

4

4 回答 4

32

在其他语言的其他数据库抽象框架中,它可用于确保您对内联值进行正确转义(对于不支持正确绑定参数的驱动程序)以及通过确保数字来提高网络效率适当打包的二进制文件(给定协议支持)。它看起来像在 PDO 中,它并没有做太多。

   if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && ! ZVAL_IS_NULL(param->parameter)) {
                if (Z_TYPE_P(param->parameter) == IS_DOUBLE) {
                        char *p;
                        int len = spprintf(&p, 0, "%F", Z_DVAL_P(param->parameter));
                        ZVAL_STRINGL(param->parameter, p, len, 0);
                } else {
                        convert_to_string(param->parameter);
                }
        } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
                convert_to_long(param->parameter);
        } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(param->parameter) == IS_LONG) {
                convert_to_boolean(param->parameter);
        }

所以,如果你说它是一个 STR (或者你什么都不说,因为这是默认值)并且你的数据的内部类型是双精度,那么它将使用一种方法将其转换为字符串,如果它不是双精度则它将使用不同的方法将其转换为字符串。

如果你说它是一个 int 但它实际上是一个 bool,那么它会将它转换为 long。

如果你说它是一个布尔值,但它实际上是一个数字,那么它将把它转换为一个真正的布尔值。

这就是我(快速)看到的所有内容,我想一旦你将参数传递给驱动程序,它们就可以发挥额外的魔力。所以,我猜你得到的只是一点点做正确的事,以及司机之间的大量行为模棱两可和差异。

于 2009-05-14T21:43:19.390 回答
21

所以我决定深入研究 PHP 源代码,这就是我发现的。

static int really_register_bound_param在 5.2.9 版的第 329 行的 ext/pdo/pdo_stmt.c 中

if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && ! ZVAL_IS_NULL(param->parameter)) {
    if (Z_TYPE_P(param->parameter) == IS_DOUBLE) {
        char *p;
        int len = spprintf(&p, 0, "%F", Z_DVAL_P(param->parameter));
        ZVAL_STRINGL(param->parameter, p, len, 0);
    } else {
        convert_to_string(param->parameter);
    }
} else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
    convert_to_long(param->parameter);
} else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(param->parameter) == IS_LONG) {
    convert_to_boolean(param->parameter);
}

这些是 PDO 在绑定期间所做的转换。

  • PDO::PARAM_STR 将您提供的任何内容转换为除 null 之外的字符串。
  • PDO::PARAM_INT 将 bool 转换为 long
  • PDO::PARAM_BOOL 将 long 转换为 bool

就是这样。没有其他任何东西被转换。PDO 使用 PARAM 标志来格式化 SQL,而不是强制转换数据类型。

于 2009-05-14T21:52:28.260 回答
6

PDO::PARAM_INT 对INSERT查询至少有一种影响:布尔值被转换为 0 或 1。就像在

$i = true;
$stmt->bindParam(':i', $v, PDO::PARAM_INT);

pdo_stmt.c:

否则如果 (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
        转换为长(参数->参数);
}

于 2009-05-07T10:49:17.163 回答
3

我用 BindValue 尝试了同样的事情并得到了相同的结果,因此您看到的行为不仅限于 bindParam。

$stmt->BindValue(':marque', $marque) ;
$stmt->BindValue(':nom', $nom, PDO::PARAM_INT) ;

$stmt->execute();
$nom = '250 GTO';
$stmt->BindValue(':nom', $nom, PDO::PARAM_INT) ;
$stmt->execute(); 
于 2009-05-14T20:38:57.877 回答