Repository: codeigniter4/CodeIgniter4 (PHP)

Issue:
Bug: orderBy method fails afrer and before calling getCompiledSelect
### PHP Version

8.3

### CodeIgniter4 Version

4.6.0, 4.6.3

### CodeIgniter4 Installation Method

Composer (as dependency to an existing project)

### Which operating systems have you tested for this bug?

Linux

### Which server did you use?

cli

### Database

both of postgresql and mysql

### What happened?

For debugging purpose, I  check my SQL with `getCompiledSelect(false)` of query builder.
Calling `orderBy()` , `getCompiledSelect()` ,  `orderBy()` failes with TypeError.


### Steps to Reproduce

Running code below anywhere (in a basic controller action or spark command) 
```php
$con = \Config\Database::connect();

$qb = $con->newQuery();
$qb->select("*")->from("t1");

echo "Calling orderBy() 1 -----\n";
$qb->orderBy("col1","desc");

echo "Calling orderBy() 2 -----\n";
$qb->orderBy("col2","desc");

$sql = $qb->getCompiledSelect(false);
echo "Result of getCompiledSelect() 1: {$sql} \n";
    
echo "Calling orderBy() 3 -----\n";
$qb->orderBy("col3","desc");

$sql = $qb->getCompiledSelect(false);
echo "Result of getCompiledSelect() 2: {$sql} \n";
```
then it fails with error:
```
[TypeError]
array_merge(): Argument #1 must be of type array, string given
at SYSTEMPATH/Database/BaseBuilder.php:1506

Backtrace:
  1    SYSTEMPATH/Database/BaseBuilder.php:1506
       array_merge('
ORDER BY `col1` DESC, `col2` DESC', [...])
```

When I remove `getCompiledSelect() 1` or `orderBy() 1 and orderBy() 2` or `orderBy() 3`,
It  runs as expected and no error occurs. 

### Expected Output

```
Calling orderBy() 1 -----
Calling orderBy() 2 -----
Result of getCompiledSelect() 1:     SELECT * FROM `t1` ORDER BY `col1` DESC, `col2` DESC
Calling orderBy() 3 -----
Result of getCompiledSelect() 2:    SELECT * FROM `t1` ORDER BY `col1` DESC, `col2` DESC, `col3` DESC 
```


### Anything else?

_No response_


Discussion:

Patch:
diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php
index 82442fbca2b1..eb2dc6f73bd2 100644
--- a/system/Database/BaseBuilder.php
+++ b/system/Database/BaseBuilder.php
@@ -3257,6 +3257,9 @@ protected function compileOrderBy(): string
     {
         if (is_array($this->QBOrderBy) && $this->QBOrderBy !== []) {
             foreach ($this->QBOrderBy as &$orderBy) {
+                if (is_string($orderBy)) {
+                    continue;
+                }
                 if ($orderBy['escape'] !== false && ! $this->isLiteral($orderBy['field'])) {
                     $orderBy['field'] = $this->db->protectIdentifiers($orderBy['field']);
                 }
@@ -3264,11 +3267,7 @@ protected function compileOrderBy(): string
                 $orderBy = $orderBy['field'] . $orderBy['direction'];
             }
 
-            return $this->QBOrderBy = "\nORDER BY " . implode(', ', $this->QBOrderBy);
-        }
-
-        if (is_string($this->QBOrderBy)) {
-            return $this->QBOrderBy;
+            return "\nORDER BY " . implode(', ', $this->QBOrderBy);
         }
 
         return '';
diff --git a/user_guide_src/source/changelogs/v4.6.4.rst b/user_guide_src/source/changelogs/v4.6.4.rst
index 121cafb9c814..b99bf17ef178 100644
--- a/user_guide_src/source/changelogs/v4.6.4.rst
+++ b/user_guide_src/source/changelogs/v4.6.4.rst
@@ -32,6 +32,7 @@ Bugs Fixed
 
 - **Database:** Fixed a bug in ``Database::connect()`` which was causing to store non-shared connection instances in shared cache.
 - **Database:** Fixed a bug in ``Connection::getFieldData()`` for ``SQLSRV`` and ``OCI8`` where extra characters were returned in column default values (specific to those handlers), instead of following the convention used by other drivers.
+- **Database:** Fixed a bug in ``BaseBuilder::compileOrderBy()`` where the method could overwrite ``QBOrderBy`` with a string instead of keeping it as an array, causing type errors and preventing additional ``ORDER BY`` clauses from being appended.
 - **Forge:** Fixed a bug in ``Postgre`` and ``SQLSRV`` where changing a column's default value using ``Forge::modifyColumn()`` method produced incorrect SQL syntax.
 - **Model:** Fixed a bug in ``Model::replace()`` where ``created_at`` field (when available) wasn't set correctly.
 


Test patch:
diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php
index 683d53a662b3..0b377e408730 100644
--- a/tests/system/Database/Builder/SelectTest.php
+++ b/tests/system/Database/Builder/SelectTest.php
@@ -407,4 +407,24 @@ public function testSelectResetQuery(): void
             str_replace("\n", ' ', $sql),
         );
     }
+
+    /**
+     * @see https://github.com/codeigniter4/CodeIgniter4/issues/9696
+     */
+    public function testGetCompiledSelect(): void
+    {
+        $builder = new BaseBuilder('users', $this->db);
+
+        $builder->select('name, role')->orderBy('name', 'desc');
+
+        $expected = 'SELECT "name", "role" FROM "users" ORDER BY "name" DESC';
+
+        $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect(false)));
+
+        $builder->orderBy('role', 'desc');
+
+        $expected = 'SELECT "name", "role" FROM "users" ORDER BY "name" DESC, "role" DESC';
+
+        $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect()));
+    }
 }