user2180613 user2180613 - 2 months ago 14
PHP Question

PHP: 7 PDO fetch(All) tries to convert types to associated type

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?

Answer

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