views:

3063

answers:

4

Hi guys, im wondering what the declaration of the data type in the bind parameter (or value) is used for...

I mean, i thougth that if i define a param like int, PDO::PARAM_INT, the param must be converted in int, something like

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

or at least throw an error if the param is not the type declared, but is not so.

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

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

that is exactly my situation. Where my thought are wrong?

+2  A: 

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

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

VolkerK
Oh.. im wondering if this effect really is usefull.. what about other data_typeS? string, etc?
DaNieL
I haven't found reliable documentation for these features. Therefore I could go through all the code in /ext/pdo* ...or simply not rely on that parameter for INSERT, UPDATE... queries.
VolkerK
Ok, i'll give a try on the SELECT queries to see if the 'problem' affet them too...Sad, anyway, that the data_type declaration would be usefull even for the sanitization/flow-control in the INSERT queries.
DaNieL
+1  A: 

I tried the same thing with BindValue and got the same result so the behavior you are seeing is not limited to 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();
gradbot
+5  A: 

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.

   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.

If you say it's an int but it is really a bool then it will convert it to a 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.

Trey
Doh, I got ninja posted. Guess I just answer slow ^^.
gradbot
Damn, I thought it did escape. /Running home to fix code.
Thomas Ahle
Ah ok, I found http://php.net/manual/en/pdo.prepared-statements.php no wories.
Thomas Ahle
+3  A: 

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

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

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::PARAM_STR converts whatever you give it to a string
  • PDO::PARAM_INT converts bools into longs
  • PDO::PARAM_BOOL converts longs into bools

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

gradbot