PHP PDO :: bindParam()数据类型..它是如何工作的?

时间:2009-05-07 08:42:58

标签: php types pdo prepared-statement

我想知道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 Ferrari 23 250 GTO   法拉利

     

这意味着如果我没有改变   是否有第三个参数。要么   也许我想念一些东西。有人可以   容忍我更多?或者只是一个人   告诉我在哪里可以找到信息   关于它。

     

此致

     

Cyruss

这正是我的情况。我的想法出了什么问题?

4 个答案:

答案 0 :(得分: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。

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

这就是我看到(快速)查看stmt源的所有内容,我想一旦你将参数传递给驱动程序,他们就可以做更多的魔术。所以,我猜你所得到的只是做了一些正确的事情以及很多行为模糊和司机之间的差异。

答案 1 :(得分:21)

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

版本5.2.9第329行的ext / pdo / pdo_stmt.c中的

static int really_register_bound_param

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将bools转换为longs
  • PDO :: PARAM_BOOL将long转换为bools

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

答案 2 :(得分:6)

PDO :: PARAM_INT对 INSERT 查询至少有一个影响:布尔值转换为0或1.类似于

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

pdo_stmt.c:

else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
        convert_to_long(param->parameter);
}

答案 3 :(得分: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();