Skip to content

Commit 3f84373

Browse files
authored
Unset _id: null to let it be autogenerated (#2969)
1 parent a017a0a commit 3f84373

File tree

4 files changed

+27
-2
lines changed

4 files changed

+27
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
44
## [4.4.0] - unreleased
55

66
* Support collection name prefix by @GromNaN in [#2930](https://github.com/mongodb/laravel-mongodb/pull/2930)
7+
* Ignore `_id: null` to let MongoDB generate an `ObjectId` by @GromNaN in [#2969](https://github.com/mongodb/laravel-mongodb/pull/2969)
78
* Add `mongodb` driver for Batching by @GromNaN in [#2904](https://github.com/mongodb/laravel-mongodb/pull/2904)
89
* Rename queue option `table` to `collection`
910
* Replace queue option `expire` with `retry_after`

src/Eloquent/Builder.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use function collect;
2222
use function is_array;
2323
use function iterator_to_array;
24+
use function json_encode;
2425

2526
/** @method \MongoDB\Laravel\Query\Builder toBase() */
2627
class Builder extends EloquentBuilder
@@ -210,8 +211,8 @@ public function raw($value = null)
210211
*/
211212
public function createOrFirst(array $attributes = [], array $values = []): Model
212213
{
213-
if ($attributes === []) {
214-
throw new InvalidArgumentException('You must provide attributes to check for duplicates');
214+
if ($attributes === [] || $attributes === ['_id' => null]) {
215+
throw new InvalidArgumentException('You must provide attributes to check for duplicates. Got ' . json_encode($attributes));
215216
}
216217

217218
// Apply casting and default values to the attributes

src/Eloquent/Model.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,12 @@ protected function isBSON(mixed $value): bool
745745
*/
746746
public function save(array $options = [])
747747
{
748+
// SQL databases would use autoincrement the id field if set to null.
749+
// Apply the same behavior to MongoDB with _id only, otherwise null would be stored.
750+
if (array_key_exists('_id', $this->attributes) && $this->attributes['_id'] === null) {
751+
unset($this->attributes['_id']);
752+
}
753+
748754
$saved = parent::save($options);
749755

750756
// Clear list of unset fields

tests/ModelTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,4 +1151,21 @@ public function testUpdateOrCreate(array $criteria)
11511151
$this->assertEquals($createdAt, $checkUser->created_at->getTimestamp());
11521152
$this->assertEquals($updatedAt, $checkUser->updated_at->getTimestamp());
11531153
}
1154+
1155+
public function testCreateWithNullId()
1156+
{
1157+
$user = User::create(['_id' => null, 'email' => 'foo@bar']);
1158+
$this->assertNotNull(ObjectId::class, $user->id);
1159+
$this->assertSame(1, User::count());
1160+
}
1161+
1162+
public function testUpdateOrCreateWithNullId()
1163+
{
1164+
$this->expectException(InvalidArgumentException::class);
1165+
$this->expectExceptionMessage('You must provide attributes to check for duplicates');
1166+
User::updateOrCreate(
1167+
['_id' => null],
1168+
['email' => 'jane.doe@example.com'],
1169+
);
1170+
}
11541171
}

0 commit comments

Comments
 (0)