Today I found out that our code appears to be backward incompatible with a change in PDO. In PHP <5.6 the result sets from a PDOStatement
through its functions fetch
and fetchAll
returned rows whose values where either a string or null. Our code relies on this attribute.
A while ago we updated to PHP 7. It turns out that PDO now attempts to convert some datatypes to other associated types. For example, a FLOAT
column creates a float value in the PDOStatement
result set. And a TINYINT
column creates an integer value in the result set. Interestingly, a BIGINT
or a large INT UNSIGNED
shows up as a string when it cannot be displayed as an integer and certain other types (such as DECIMAL
) are not converted to anything. They remain strings. I thought it was a generally agreed upon principle that converting data types from a MySQL database to PHP data types is problematic and should not be carried out by PHP itself, but apparently PHP 7 decided otherwise.
So PHP 7's PDO introduces a set of conversion rules that it uses internally to convert values selected from a database, but that screws up my code base and because of the inconsistencies of these conversion rules, I'd rather not change my code base to suit them. Is there maybe some sort of setting or flag which I can toggle to prevent PDO from converting the values it fetches?
Fetch data from a result set by calling one of the following fetch methods: To return a single row from a result set as an array or object, call the PDOStatement::fetch method. To return all of the rows from the result set as an array of arrays or objects, call the PDOStatement::fetchAll method.
PDOStatement::fetchAll() returns an array containing all of the remaining rows in the result set. The array represents each row as either an array of column values or an object with properties corresponding to each column name. An empty array is returned if there are zero results to fetch.
PDO::FETCH_ASSOC. Returns an array indexed by column name as returned in your result set. PDO::FETCH_BOTH (default) Returns an array indexed by both column name and 0-indexed column number as returned in your result set.
PDO::FETCH_NUM. Returns an array indexed by column number as returned in your result set, starting at column 0. PDO::FETCH_OBJ. Returns an anonymous object with property names that correspond to the column names returned in your result set.
It is not PHP7 but the underlying driver called mysqlnd.
Also, it is not a set of conversion rules but the way the transport protocol works: when both mysqlnd and native prepatred statements are used, then the binary transport protocol is used, means there is always an information about the data type. So the data just gets unpacked from the binary format right into a variable of the proper type - when PHP has an appropriate one, namely INTs and FLOATs (note that for the DECIMAL type string is returned, due to nature of this type).
In case you don't want this behavior, there is a configuration option for this
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
will revert this behavior to just strings and nulls as before
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With