Question

I'm facing the problem described by Steve M but on a "large scale", please see for details http://www.php.net/manual/en/pdostatement.bindparam.php#94711

I'm using Phalcon, but it mostly acts as a wrapper, the question must not be limited by that. The detailed issue is here – https://github.com/phalcon/cphalcon/issues/2111

TL;DR Int values in array are converted to strings, as such:

var_dump($params); // array(2) { [0]=> int(6609) [1]=> int(6664) }
$adapter->fetchAll($sql, Db::FETCH_ASSOC, $params);
var_dump($params); // array(2) { [0]=> string(4) "6609" [1]=> string(4) "6664" }

I reuse that array later and heavily rely on the ints. When they turn into strings it spoils all the joy… No matter what I do with it (copies values with foreach , array_merge into new array, ArrayObject::getArrayCopy to get a copy) the original values keep changing (and values of other arrays they've been copied from). They only way with copying that works is:

$adapter->fetchAll($sql, Db::FETCH_ASSOC, unserialize(serialize(($params)));

That feels like an massive overkill. Another solution that seems to work is below, though $paramTypes is not documented (Phalcon code that handles it for those who're interested).

$paramTypes = [];                                                                                                                                               
foreach ($params as $param) {                                                   
    if (is_int($param)) {                                                       
        $paramTypes[] = \PDO::PARAM_INT;                                        
    } else {                                                                    
        $paramTypes[] = null;                                                   
    }                                                                           
}                                                                               
$rows = $this->adapter->fetchAll($sql, Db::FETCH_ASSOC, $params, $paramTypes);  

To me it seems to be the best approach, BUT here is the same method described by Axeia that received negative feedback – http://www.php.net/manual/en/pdo.constants.php#97130.

My questions:

  1. Why it might be a bad idea doing it the way Axeia suggests?
  2. Can you suggest another alternative to this? Apart from converting the modified array back to integers.
  3. WTF???!!! Why it need to take a reference and modify it? Should there be a bug report???

Many thanks ya all!

Was it helpful?

Solution 2

The problem was with the fact that Phalcon inadequately did use PDOStatement::bindParam instead of PDOStatement::bindValue. The big debate is covered on the github and followed with a pull request, which eventually has been merged into version 1.3.2.

OTHER TIPS

Your mysql database will keep data type as it is width php-mysqlnd driver and these two attributes set to false:

$dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$parm1 = 2;
var_dump($parm1);
//  int(2)

$sth = $dbh->prepare('SELECT *  FROM test.table1  WHERE id = ?');
$sth->bindParam(1, $parm1, PDO::PARAM_INT);
$sth->execute();
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
var_dump($parm1);
// int(2)

var_dump($data);

/* you get nice and clean result:
array(1) {
  [0]=>
  array(4) {
    ["id"]=>  int(2)
    ["name"]=>  string(3) "XYZ"
    ["someint"]=>  int(543)
    ["somefloat"]=>   float(1000.0001220703)
  }
}

And table is:
CREATE TABLE `table1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `someint` int(8) DEFAULT NULL,
  `somefloat` float(10,5) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

*/
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top