Skip to content

Commit

Permalink
Unset _id null to let it be autogenerated
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN committed May 22, 2024
1 parent e8a8902 commit 8ca5940
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use function collect;
use function is_array;
use function iterator_to_array;
use function json_encode;

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

// Apply casting and default values to the attributes
Expand All @@ -233,8 +234,8 @@ public function createOrFirst(array $attributes = [], array $values = []): Model
try {
$document = $collection->findOneAndUpdate(
$attributes,
// Before MongoDB 5.0, $setOnInsert requires a non-empty document.
// This should not be an issue as $values includes the query filter.
// Before MongoDB 5.0, $setOnInsert requires a non-empty document,
// this should not be an issue as $values include the query filter.
['$setOnInsert' => (object) $values],
[
'upsert' => true,
Expand Down
6 changes: 6 additions & 0 deletions src/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,12 @@ protected function isBSON(mixed $value): bool
*/
public function save(array $options = [])
{
// SQL databases would use autoincrement the id field if set to null.
// Apply the same behavior to MongoDB with _id only, otherwise null would be stored.
if (array_key_exists('_id', $this->attributes) && $this->attributes['_id'] === null) {
unset($this->attributes['_id']);
}

$saved = parent::save($options);

// Clear list of unset fields
Expand Down
17 changes: 17 additions & 0 deletions tests/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1151,4 +1151,21 @@ public function testUpdateOrCreate(array $criteria)
$this->assertEquals($createdAt, $checkUser->created_at->getTimestamp());
$this->assertEquals($updatedAt, $checkUser->updated_at->getTimestamp());
}

public function testCreateWithNullId()
{
$user = User::create(['_id' => null, 'email' => 'foo@bar']);
$this->assertNotNull(ObjectId::class, $user->id);
$this->assertSame(1, User::count());
}

public function testUpdateOrCreateWithNullId()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('You must provide attributes to check for duplicates');
User::updateOrCreate(
['_id' => null],
['email' => 'jane.doe@example.com'],
);
}
}

0 comments on commit 8ca5940

Please sign in to comment.