A very important DaDaBIK patch, especially if you are using PHP 8.1

eugenio

Administrator
Staff member
Hello,
let me introduce the topic with some background, I'll try to be synthetic and to simplify as much as possible.

Background

When, in PHP PDO, you read data from a database (technically, when you fetch a record), often the field type is converted to string even if it is a numeric (integer or float) field.
So, for example, you store the value (e.g. 10) contained in the field id_customer (int) into an $id_customer variable and the $id_customer value will become '10' (a string).

What does often mean? This would open a long parenthesis but let's say that conversion to string was a sort of "standard" in the early days of PHP/MySQL applications but then things changed and it depends on the combination of DBMS (MySQL, PostgreSQL, ... ) & PHP version and on some settings. So with some combinations of DBMS, PHP & settings, the integer value 10 remains 10 (integer), with some others, 10 becomes '10'.

Starting from PHP 8.1, at least for some DBMSs (MySQL and SQLite), integers and floats are now (apparently always) returned using native PHP types instead of strings (so integer 10 will remain integer 10).
For PostgreSQL and MS SQL Server, at least according to my tests, the situation si different: the PostgreSQL driver did not convert to string (even before PHP 8.1), MS SQL SERVER still converts to string (even with PHP 8.1) but depending on a PDO setting, it can also avoid conversion.

Why this matters

Because in the DaDaBIK core code (and also in your own custom code) if the identical (===) or not identical (!==) operators are used to compare two variables, not only the value but also the type of the two variables is compared. More in general, if in your code you check the type of a variable, the result changes according to the way records are fetched.

If your custom code is based on the assumption of fetching all the values as string, your code may stop working with PHP 8.1 (and maybe did not work correctly even with PHP 7, depending on your DBMS and settings). For example if you check if the current user belongs to the group 2 in this way:

PHP:
if ($current_id_group === '2')

you will always get FALSE, because $current_id_group is now integer.

Every time you use values coming from the database you may have an impact, not only values you retrieve in your own queries, but also other values you get from DaDaBIK. For example a custom formatting function receives in input the value of the unique field of the record processed ($id); if your id is integer in the DB, the $id variable you get could be string in PHP 7.4 and integer on PHP 8.1 (I use the conditional because, as I said, this also depends on DBMS and settings).

What you should do

First of all, I strongly recommend to upgrade to PHP 8, since in about one month, PHP 7.4 will not receive security updates from the PHP development team (but this is another story).

DaDaBIK has been developed assuming int and float fields are converted to string, however, the code works even if int and float are not converted during fetching. At the moment, I am not aware of any bugs in DaDaBIK related to this fetching matter.

However, since there could be sneaky cases that have not emerged and that could lead to unexpected behaviours, I suggest to apply a patch that forces PHP, in any situation (with both PHP 7 and 8), to always apply string conversion during fetching. This allow us to be sure we have the same situation regardless of the PHP version, DBMS type and additional settings you may have.

In addition to that, there is your own custom code, that cannot be controlled by DaDaBIK and that you have to check (more details later in this message).

Here is the patch:

1) Open the file /include/db_functions_pdo.php
2) Search the connect_db function (it should be the first one)
3) Add this line:

PHP:
$conn->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);

at the end of the connect_db(), just before:

PHP:
return $conn;

So your connect_db() function will end with:

$conn->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); return $conn; }

This patch is for DaDaBIK V 11.7 but you should see identical code if your DaDaBIK version is relatively recent.

The patch only has effect on the main db connection created by DaDaBIK (the $conn object), it does not impact on other connections you may have opened in your custom code.

You also have to check your custom code and to assume, in your code, string conversion.

Finally, consider that with PHP 8.1, if you apply the patch, values of type bool are stringified to "0" or "1", previously to PHP 8.1 they weren't stringified. However, DB bool type are currently not supported in DaDaBIK so this shouldn't have an impact (at least on the DaDaBIK core code).

I have also published a script that, for any DaDaBIK installation (before and after the patch, with PHP 7 or 8), can tell you in which situation you are (string conversion applied Vs. string conversion not applied). The script is here (md5 checksum: c81a66e1a222901e68313cbdf0d0070b) and contains installation instructions as comments.

That's it. Sorry for the long message.

Best,
 

eugenio

Administrator
Staff member
An additional note: depending on the DaDaBIK edition you have and on when you downloaded it, you could have the patch (that line in db_functions_pdo.php) already there. The patch will be officially applied to all the editions of DaDaBIK starting from the next release.
 
Top