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
.
source to share
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.
source to share