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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/833510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:01:05  来源:igfitidea点击:

PHP PDO::bindParam() data types.. how does it work?

phptypespdoprepared-statement

提问by Strae

I'm wondering what the declaration of the data type in bindParam()(or bindValue()) is used for...

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

I mean, I thought that if I define an integer argument (PDO::PARAM_INT), the argument must be converted to an integer, something like

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

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

or at least throw an error if the argument is not of the declared type. But this is not the case.

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

Googling around, I found that in the php.net archive:

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

Hi all,

I am currently working on PDO. Exactly on the bindParam() function. The third parameter data_type seems to be here to force the type of the value ? But when I try :

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

I was expecting to have either a PHP error or an interger in my database. But in my DB I have :

22 Testarossa Ferrari 23 250 GTO Ferrari

It mean that it didn't change if I have the third parameter or not. Or perhaps I miss something. Can someone tole me more ? Or just can someone told me where I can find information about it.

Regards,

Cyruss

大家好,

我目前正在研究 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 泰斯塔罗萨法拉利 23 250 GTO 法拉利

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

问候,

赛勒斯

That is exactly my situation. Where are my thoughts going wrong?

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

回答by Trey

In other DB abstraction frameworks in other languages it can be used for things like making sure you're doing the proper escaping for in-lining values (for drivers that don't support proper bound parameters) and improving network efficiency by making sure numbers are binary packed appropriately (given protocol support). It looks like in PDO, it doesn't do much.

在其他语言的其他数据库抽象框架中,它可用于确保您对内联值(对于不支持正确绑定参数的驱动程序)进行正确转义以及通过确保数字是正确的来提高网络效率等事情二进制打包适当(给定协议支持)。它看起来像在 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);
        }

So, if you say it is a STR (or if you say nothing at all as that is the default) and your data's internal type is a double then it will turn it into a string using one method, if it's not a double then it will convert it to a string using a different method.

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

If you say it's an int but it is really a bool then it will convert it to a long.

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

If you say it's a bool but it's really a number then it will convert it to a true boolean.

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

This is really all I saw (quickly) looking at the stmt source, I imagine once you pass the parameters into the driver they can do additional magic. So, I'd guess that all you get is a little bit of do the right and a whole lot of behavior ambiguity and variance between drivers.

这就是我看到的(快速)查看 stmt 源代码的全部内容,我想一旦您将参数传递给驱动程序,它们就可以发挥额外的作用。所以,我猜你得到的只是一点点做正确的事,以及司机之间的大量行为模糊和差异。

回答by gradbot

So I decided to dive into the PHP source code and this is what I found.

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

static int really_register_bound_paramin ext/pdo/pdo_stmt.c on line 329 of version 5.2.9

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

These are the conversions PDO does during binding.

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

  • PDO::PARAM_STR converts whatever you give it to a string except null.
  • PDO::PARAM_INT converts bools into longs
  • PDO::PARAM_BOOL converts longs into bools
  • PDO::PARAM_STR 将您提供的任何内容转换为除 null 之外的字符串。
  • PDO::PARAM_INT 将 bool 转换为 long
  • PDO::PARAM_BOOL 将 long 转换为 bool

That's it. Nothing else is converted. PDO uses the PARAM flags to format SQL not to cast data types.

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

回答by VolkerK

There's at least one effect PDO::PARAM_INT has on INSERTqueries: boolean values are converted to 0 or 1. Like in

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

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

pdo_stmt.c:

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

回答by gradbot

I tried the same thing with BindValue and got the same result so the behavior you are seeing is not limited to bindParam.

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