diff --git a/CHANGELOG.md b/CHANGELOG.md index c0e383338..e9f973800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [5.1.0] - next * Convert `_id` and `UTCDateTime` in results of `Model::raw()` before hydratation by @GromNaN in [#3152](https://github.com/mongodb/laravel-mongodb/pull/3152) +* Alias `_id` to `id` in `Schema::getColumns()` by @GromNaN in [#3160](https://github.com/mongodb/laravel-mongodb/pull/3160) ## [5.0.2] - 2024-09-17 diff --git a/src/Schema/Builder.php b/src/Schema/Builder.php index 630ff4c75..ade4b0fb7 100644 --- a/src/Schema/Builder.php +++ b/src/Schema/Builder.php @@ -9,14 +9,19 @@ use MongoDB\Model\IndexInfo; use function array_fill_keys; +use function array_filter; use function array_keys; +use function array_map; use function assert; use function count; use function current; use function implode; +use function in_array; use function iterator_to_array; use function sort; use function sprintf; +use function str_ends_with; +use function substr; use function usort; class Builder extends \Illuminate\Database\Schema\Builder @@ -40,6 +45,16 @@ public function hasColumn($table, $column): bool */ public function hasColumns($table, array $columns): bool { + // The field "id" (alias of "_id") always exists in MongoDB documents + $columns = array_filter($columns, fn (string $column): bool => ! in_array($column, ['_id', 'id'], true)); + + // Any subfield named "*.id" is an alias of "*._id" + $columns = array_map(fn (string $column): string => str_ends_with($column, '.id') ? substr($column, 0, -3) . '._id' : $column, $columns); + + if ($columns === []) { + return true; + } + $collection = $this->connection->table($table); return $collection @@ -187,16 +202,21 @@ public function getColumns($table) foreach ($stats as $stat) { sort($stat->types); $type = implode(', ', $stat->types); + $name = $stat->_id; + if ($name === '_id') { + $name = 'id'; + } + $columns[] = [ - 'name' => $stat->_id, + 'name' => $name, 'type_name' => $type, 'type' => $type, 'collation' => null, - 'nullable' => $stat->_id !== '_id', + 'nullable' => $name !== 'id', 'default' => null, 'auto_increment' => false, 'comment' => sprintf('%d occurrences', $stat->total), - 'generation' => $stat->_id === '_id' ? ['type' => 'objectId', 'expression' => null] : null, + 'generation' => $name === 'id' ? ['type' => 'objectId', 'expression' => null] : null, ]; } diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index 0f04ab6d4..ff3dfe626 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -374,14 +374,22 @@ public function testRenameColumn(): void public function testHasColumn(): void { - DB::connection()->table('newcollection')->insert(['column1' => 'value']); + $this->assertTrue(Schema::hasColumn('newcollection', '_id')); + $this->assertTrue(Schema::hasColumn('newcollection', 'id')); + + DB::connection()->table('newcollection')->insert(['column1' => 'value', 'embed' => ['_id' => 1]]); $this->assertTrue(Schema::hasColumn('newcollection', 'column1')); $this->assertFalse(Schema::hasColumn('newcollection', 'column2')); + $this->assertTrue(Schema::hasColumn('newcollection', 'embed._id')); + $this->assertTrue(Schema::hasColumn('newcollection', 'embed.id')); } public function testHasColumns(): void { + $this->assertTrue(Schema::hasColumns('newcollection', ['_id'])); + $this->assertTrue(Schema::hasColumns('newcollection', ['id'])); + // Insert documents with both column1 and column2 DB::connection()->table('newcollection')->insert([ ['column1' => 'value1', 'column2' => 'value2'], @@ -451,8 +459,9 @@ public function testGetColumns() $this->assertIsString($column['comment']); }); - $this->assertEquals('objectId', $columns->get('_id')['type']); - $this->assertEquals('objectId', $columns->get('_id')['generation']['type']); + $this->assertNull($columns->get('_id'), '_id is renamed to id'); + $this->assertEquals('objectId', $columns->get('id')['type']); + $this->assertEquals('objectId', $columns->get('id')['generation']['type']); $this->assertNull($columns->get('text')['generation']); $this->assertEquals('string', $columns->get('text')['type']); $this->assertEquals('date', $columns->get('date')['type']);