Repository: codeigniter4/CodeIgniter4 (PHP)

Issue:
Bug: Builder insert()/update() does not accept an object
### PHP Version

7.4

### CodeIgniter4 Version

4.0.4 

### CodeIgniter4 Installation Method

Manual (zip or tar.gz)

### Which operating systems have you tested for this bug?

Linux

### Which server did you use?

apache

### Database

MySQL 5.56

### What happened?

Hi, I have a problem with DB Builder 
Log:
`CRITICAL - 2022-06-30 09:24:34 --> Argument 1 passed to CodeIgniter\Database\BaseBuilder::update() must be of the type array or null, object given, called in ....php on line 41 `

My mine 40 & line 41: 
```php
$builder = $this->dbmail->table(self::TABLE); 
$builder->update($undelivered, ['undelivered_id' => $undelivered->undelivered_id]); 
```

According to documentation: 
```php
$object = new Myclass(); 
$builder->where('id', $id); 
$builder->update($object); 
```
https://codeigniter4.github.io/CodeIgniter4/database/query_builder.html#builder-update

Builder insert() have a same problem.

### Steps to Reproduce

Just do Builder update with object.

### Expected Output

No critical or any other error

### Anything else?

 Looks like the error is in all versions from 4.0.4 until current


Discussion:
1. You should update the framework. Preferably up to the latest version, as many bugs and vulnerabilities have been fixed.
2. This is a documentation error. The update() and insert() methods currently only expect arrays.
You can use the set() method to pass data instead of passing it to the update()/insert() methods.
```php
$builder->set($object)->where()->update();
```
The API is changed a bit, but an object can be inserted since v3.
https://www.codeigniter.com/userguide3/database/query_builder.html#inserting-data

I think this is a bug of the implementation and should be fixed.




Patch:
diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php
index 5c7f752c65b6..4f835730d176 100644
--- a/system/Database/BaseBuilder.php
+++ b/system/Database/BaseBuilder.php
@@ -1878,11 +1878,13 @@ public function getCompiledInsert(bool $reset = true)
     /**
      * Compiles an insert string and runs the query
      *
+     * @param array|object|null $set
+     *
      * @throws DatabaseException
      *
      * @return bool|Query
      */
-    public function insert(?array $set = null, ?bool $escape = null)
+    public function insert($set = null, ?bool $escape = null)
     {
         if ($set !== null) {
             $this->set($set, '', $escape);
@@ -2012,11 +2014,12 @@ public function getCompiledUpdate(bool $reset = true)
     /**
      * Compiles an update string and runs the query.
      *
-     * @param mixed $where
+     * @param array|object|null        $set
+     * @param array|RawSql|string|null $where
      *
      * @throws DatabaseException
      */
-    public function update(?array $set = null, $where = null, ?int $limit = null): bool
+    public function update($set = null, $where = null, ?int $limit = null): bool
     {
         if ($set !== null) {
             $this->set($set);
diff --git a/user_guide_src/source/changelogs/v4.2.2.rst b/user_guide_src/source/changelogs/v4.2.2.rst
index 5bd45500b3b9..45fbeb205d54 100644
--- a/user_guide_src/source/changelogs/v4.2.2.rst
+++ b/user_guide_src/source/changelogs/v4.2.2.rst
@@ -14,6 +14,7 @@ BREAKING
 
 - Now ``Services::request()`` returns ``IncomingRequest`` or ``CLIRequest``.
 - The method signature of ``CodeIgniter\Debug\Exceptions::__construct()`` has been changed. The ``IncomingRequest`` typehint on the ``$request`` parameter was removed. Extending classes should likewise remove the parameter so as not to break LSP.
+- The method signature of ``BaseBuilder.php::insert()`` and ``BaseBuilder.php::update()`` have been changed. The ``?array`` typehint on the ``$set`` parameter was removed.
 
 Enhancements
 ************


Test patch:
diff --git a/tests/system/Database/Builder/InsertTest.php b/tests/system/Database/Builder/InsertTest.php
index 2e6d3b89650e..daa605be40f9 100644
--- a/tests/system/Database/Builder/InsertTest.php
+++ b/tests/system/Database/Builder/InsertTest.php
@@ -33,7 +33,7 @@ protected function setUp(): void
         $this->db = new MockConnection([]);
     }
 
-    public function testSimpleInsert()
+    public function testInsertArray()
     {
         $builder = $this->db->table('jobs');
 
@@ -59,6 +59,32 @@ public function testSimpleInsert()
         $this->assertSame($expectedBinds, $builder->getBinds());
     }
 
+    public function testInsertObject()
+    {
+        $builder = $this->db->table('jobs');
+
+        $insertData = (object) [
+            'id'   => 1,
+            'name' => 'Grocery Sales',
+        ];
+        $builder->testMode()->insert($insertData, true);
+
+        $expectedSQL   = 'INSERT INTO "jobs" ("id", "name") VALUES (1, \'Grocery Sales\')';
+        $expectedBinds = [
+            'id' => [
+                1,
+                true,
+            ],
+            'name' => [
+                'Grocery Sales',
+                true,
+            ],
+        ];
+
+        $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledInsert()));
+        $this->assertSame($expectedBinds, $builder->getBinds());
+    }
+
     public function testThrowsExceptionOnNoValuesSet()
     {
         $builder = $this->db->table('jobs');
diff --git a/tests/system/Database/Builder/UpdateTest.php b/tests/system/Database/Builder/UpdateTest.php
index 5af1490f6f66..55eec68b8f2a 100644
--- a/tests/system/Database/Builder/UpdateTest.php
+++ b/tests/system/Database/Builder/UpdateTest.php
@@ -34,11 +34,35 @@ protected function setUp(): void
         $this->db = new MockConnection([]);
     }
 
-    public function testUpdate()
+    public function testUpdateArray()
     {
         $builder = new BaseBuilder('jobs', $this->db);
 
-        $builder->testMode()->where('id', 1)->update(['name' => 'Programmer'], null, null);
+        $data = ['name' => 'Programmer'];
+        $builder->testMode()->where('id', 1)->update($data, null, null);
+
+        $expectedSQL   = 'UPDATE "jobs" SET "name" = \'Programmer\' WHERE "id" = 1';
+        $expectedBinds = [
+            'id' => [
+                1,
+                true,
+            ],
+            'name' => [
+                'Programmer',
+                true,
+            ],
+        ];
+
+        $this->assertSame($expectedSQL, str_replace("\n", ' ', $builder->getCompiledUpdate()));
+        $this->assertSame($expectedBinds, $builder->getBinds());
+    }
+
+    public function testUpdateObject()
+    {
+        $builder = new BaseBuilder('jobs', $this->db);
+
+        $data = (object) ['name' => 'Programmer'];
+        $builder->testMode()->where('id', 1)->update($data, null, null);
 
         $expectedSQL   = 'UPDATE "jobs" SET "name" = \'Programmer\' WHERE "id" = 1';
         $expectedBinds = [