diff --git a/system/Database/Forge.php b/system/Database/Forge.php index 8ad39ae5a574..c95ced88c4d6 100644 --- a/system/Database/Forge.php +++ b/system/Database/Forge.php @@ -387,12 +387,25 @@ public function addField($field) throw new InvalidArgumentException('Field information is required for that operation.'); } - $this->fields[] = $field; + $fieldName = explode(' ', $field, 2)[0]; + $fieldName = trim($fieldName, '`\'"'); + + $this->fields[$fieldName] = $field; } } if (is_array($field)) { - $this->fields = array_merge($this->fields, $field); + foreach ($field as $idx => $f) { + if (is_string($f)) { + $this->addField($f); + + continue; + } + + if (is_array($f)) { + $this->fields = array_merge($this->fields, [$idx => $f]); + } + } } return $this; @@ -878,7 +891,7 @@ protected function _processFields(bool $createTable = false): array $fields = []; foreach ($this->fields as $key => $attributes) { - if (is_int($key) && ! is_array($attributes)) { + if (! is_array($attributes)) { $fields[] = ['_literal' => $attributes]; continue; diff --git a/tests/system/Database/Live/ForgeTest.php b/tests/system/Database/Live/ForgeTest.php index 63681115f2ad..1eba35919068 100644 --- a/tests/system/Database/Live/ForgeTest.php +++ b/tests/system/Database/Live/ForgeTest.php @@ -415,6 +415,43 @@ public function testForeignKey() $this->forge->dropTable('forge_test_users', true); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/4986 + */ + public function testForeignKeyAddingWithStringFields() + { + if ($this->db->DBDriver !== 'MySQLi') { + $this->markTestSkipped('Testing only on MySQLi but fix expands to all DBs.'); + } + + $attributes = ['ENGINE' => 'InnoDB']; + + $this->forge->addField([ + '`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY', + '`name` VARCHAR(255) NOT NULL', + ])->createTable('forge_test_users', true, $attributes); + + $this->forge + ->addField([ + '`id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY', + '`users_id` INT(11) NOT NULL', + '`name` VARCHAR(255) NOT NULL', + ]) + ->addForeignKey('users_id', 'forge_test_users', 'id', 'CASCADE', 'CASCADE') + ->createTable('forge_test_invoices', true, $attributes); + + $foreignKeyData = $this->db->getForeignKeyData('forge_test_invoices')[0]; + + $this->assertSame($this->db->DBPrefix . 'forge_test_invoices_users_id_foreign', $foreignKeyData->constraint_name); + $this->assertSame('users_id', $foreignKeyData->column_name); + $this->assertSame('id', $foreignKeyData->foreign_column_name); + $this->assertSame($this->db->DBPrefix . 'forge_test_invoices', $foreignKeyData->table_name); + $this->assertSame($this->db->DBPrefix . 'forge_test_users', $foreignKeyData->foreign_table_name); + + $this->forge->dropTable('forge_test_invoices', true); + $this->forge->dropTable('forge_test_users', true); + } + public function testForeignKeyFieldNotExistException() { $this->expectException(DatabaseException::class);