Using named parameters multiple times versus return data types in PDO

Sorry for the long text. The factual question is at the end of this text.

I just switched from mysqli

to PDO

.

Using mysqli

, I got data from my database like this:

$db = new mysqli($host,$user,$pass,$dbName);
$db->query('SET NAMES utf8');

$stmt = $db->prepare('SELECT field FROM table WHERE other_field = ?');
$stmt->bind_param('i', 1);   // could also be something else
$stmt->execute();
$stmt->bind_result($field);
$stmt->fetch();   // maybe in a loop
...

      

At the end $field

contains the value of the field in the database (one row). But it also has the data type of this field. Therefore, if field

declared as TINYINT

, $field

contains integers, if declared as string, it contains string, and if the value in the database NULL

is $field

set to NULL

.

After switching to PDO

my code it looks like this:

$db = new PDO('mysql:host=127.0.0.1;dbname=my_db;charset=UTF8',$user,$pass);

$stmt = $db->prepare('SELECT field FROM table WHERE other_field = ?');
$stmt->execute([1]);
$stmt->bindColumn(1,$field,PDO::PARAM_INT);   // maybe an other datatype
$stmt->fetch(PDO::FETCH_BOUND);   // maybe in a loop

      

This way I can figure out what type of data it should return.

But strange things are happening now.

If a field in the database contains NULL

, it is changed to 0

(integer) if I use PDO::PARAM_INT

or false

if I use PDO::PARAM_BOOL

. So I can't see if the value is really NULL

or false

. This is similar to all methods of getting data.
After some research, I found that this can be fixed by turning off prepared statements. So, now I am connecting to my database like this:

$db = new PDO('mysql:host=127.0.0.1;dbname=my_db;charset=UTF8',$user, $pass,
               [PDO::ATTR_EMULATE_PREPARES => false]); 

      

The returned data types now work very well.

However, turning off emulated prepared statements also removes the ability to use named parameters multiple times.

eg.

$stmt = $db->prepare('SELECT * FROM table 
                      WHERE date_val BETWEEN :date AND :date + INTERVAL 6 DAY')
$stmt->execute(['date' => '2015-06-15']);

      

This works fine if emulated prepared statements are enabled, but it results in an error HY093

(Invalid parameter number) if disabled.

So my question is:
Is there a parameter PDO

that allows both, the correct return data types (including NULL

s) and the named parameters to be used multiple times, or do I have to drop one?

Note. I know I can write a function to fix named parameters if they are used multiple times, or use a different workaround, but I am looking for a PDO setting or a parameter passed to the PDO function. If there is no such setting, I will discard the named parameters and stay with the parameters ?

that I already used with mysqli

.

+3


source to share


1 answer


After much more research, I didn't find a solution, but a bug report ( # 69257 ).

According to this report, it is a bug that you can only use named parameters multiple times with emulated prepared statements.



I have now reported the behavior bindColumn

for the PHP bug tracker ( # 69856 ).

We hope both will be fixed sometimes.

0


source







All Articles