Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: [Model] Limitation in Boolean Support (true/false) in update()/save()/insert() #9197

Open
datamweb opened this issue Sep 20, 2024 · 2 comments
Labels
bug Verified issues on the current code behavior or pull requests that will fix them

Comments

@datamweb
Copy link
Contributor

PHP Version

8.3

CodeIgniter4 Version

v4.5.4

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

apache

Database

No response

What happened?

$this->update($messageId, [
  'is_pinned'     => false,
]);
 ------ ------------------------------------------------------------------------------------------------------
  Line   src\Models\MessageModel.php
 ------ ------------------------------------------------------------------------------------------------------
  107    Parameter #2 $row of method Datamweb\BlankPackage\Models\BaseModel::update() expects array<int|string,
         float|int|object|string|null>|object|null, array<string, int|false|null> given.
 ------ ------------------------------------------------------------------------------------------------------

Currently, CodeIgniter 4 does not support boolean values (true and false) in models due to restrictions in the PHPStan typing declaration (@phpstan-type row_array).

* @phpstan-type row_array array<int|string, float|int|null|object|string>

This definition only allows int, float, null, string, and object types, effectively preventing boolean values from being used in database operations.

This issue is particularly problematic because certain database drivers natively support boolean values, and they should be allowed for use directly.

Database Driver Details

Database Boolean Support Data Type Accepted Values
MySQL Yes TINYINT(1) true / false (1/0)
PostgreSQL Yes BOOLEAN true / false
SQL Server Yes BIT true / false (1/0)
SQLite No (requires conversion) INTEGER 1 / 0
OCI8 (Oracle) No (requires conversion) NUMBER 1 / 0

Steps to Reproduce

To address this limitation and allow boolean values, it is suggested to:

  1. Update the PHPStan-type declaration to support boolean values (true and false) for all supported databases.
* @phpstan-type row_array               array<int|string, float|int|null|object|string|bool> 
  1. Add automatic conversion for databases that do not support boolean values directly (like SQLite and OCI8) by converting true to 1 and false to 0.

Example Code for Handling Boolean Conversion

protected function prepareDataForSQLiteAndOCI8(array $data): array
{
    $dbDriver = $this->db->DBDriver;

    if ($dbDriver === 'SQLite3' || $dbDriver === 'OCI8') {
        foreach ($data as $key => $value) {
            if (is_bool($value)) {
                $data[$key] = $value ? 1 : 0;
            }
        }
    }

    return $data;
}

These changes will ensure better compatibility with all database drivers, allowing proper handling of boolean values in databases that do not natively support them.

Expected Output

Manually casting boolean values is a workaround and places unnecessary burden on developers. CodeIgniter 4 should handle these conversions internally, especially given that:

Many database drivers natively support boolean values (true and false).
The framework should abstract away such differences, allowing developers to focus on business logic rather than database-specific nuances.

In conclusion, while manual casting (e.g., (int)false OR 1/0) solves the problem for now, this limitation should not exist, as proper support for boolean values will make the framework more robust and user-friendly.

Anything else?

No response

@datamweb datamweb added the bug Verified issues on the current code behavior or pull requests that will fix them label Sep 20, 2024
@kenjis kenjis changed the title Bug: Limitation in Boolean Support (true/false) in update()/save()/insert() Bug: [Model] Limitation in Boolean Support (true/false) in update()/save()/insert() Sep 24, 2024
@kenjis
Copy link
Member

kenjis commented Sep 24, 2024

It seems bool is missing in the PHPDoc type.

@michalsn
Copy link
Member

If only PHPDoc is on the way to supporting booleans, then that's a good thing to change.

I'm not a big fan of point 2. This would mean that each write query would be subject to an additional loop check of all passed arguments. Seems like a big waste of time/resources - for this one thing.

If we want "magic" we have Entities or Data conversion in the model. When we use Query Builder we're responsible for the values we use/allow. If a certain database does not support booleans, it's not a framework's fault.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Verified issues on the current code behavior or pull requests that will fix them
Projects
None yet
Development

No branches or pull requests

3 participants