diff --git a/CHANGELOG.md b/CHANGELOG.md index 73a4faa8b..e8ba4e0f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. * Add `Schema\Builder::getTables()` and `getTableListing()` by @GromNaN in [#3044](https://github.com/mongodb/laravel-mongodb/pull/3044) * Add `Schema\Builder::getColumns()` and `getIndexes()` by @GromNaN in [#3045](https://github.com/mongodb/laravel-mongodb/pull/3045) * Add `Schema\Builder::hasColumn` and `hasColumns` method by @Alex-Belyi in [#3001](https://github.com/mongodb/laravel-mongodb/pull/3001) +* Fix unsetting a field in an embedded model by @GromNaN in [#3052](https://github.com/mongodb/laravel-mongodb/pull/3052) ## [4.6.0] - 2024-07-09 diff --git a/src/Relations/EmbedsOneOrMany.php b/src/Relations/EmbedsOneOrMany.php index 9c83aa299..f18d3d526 100644 --- a/src/Relations/EmbedsOneOrMany.php +++ b/src/Relations/EmbedsOneOrMany.php @@ -15,8 +15,10 @@ use Throwable; use function array_merge; +use function assert; use function count; use function is_array; +use function str_starts_with; use function throw_if; abstract class EmbedsOneOrMany extends Relation @@ -392,7 +394,12 @@ public static function getUpdateValues($array, $prepend = '') $results = []; foreach ($array as $key => $value) { - $results[$prepend . $key] = $value; + if (str_starts_with($key, '$')) { + assert(is_array($value), 'Update operator value must be an array.'); + $results[$key] = static::getUpdateValues($value, $prepend); + } else { + $results[$prepend . $key] = $value; + } } return $results; diff --git a/tests/EmbeddedRelationsTest.php b/tests/EmbeddedRelationsTest.php index 00a84360c..22e6e8d08 100644 --- a/tests/EmbeddedRelationsTest.php +++ b/tests/EmbeddedRelationsTest.php @@ -10,12 +10,6 @@ use Mockery; use MongoDB\BSON\ObjectId; use MongoDB\Laravel\Tests\Models\Address; -use MongoDB\Laravel\Tests\Models\Book; -use MongoDB\Laravel\Tests\Models\Client; -use MongoDB\Laravel\Tests\Models\Group; -use MongoDB\Laravel\Tests\Models\Item; -use MongoDB\Laravel\Tests\Models\Photo; -use MongoDB\Laravel\Tests\Models\Role; use MongoDB\Laravel\Tests\Models\User; use function array_merge; @@ -25,14 +19,7 @@ class EmbeddedRelationsTest extends TestCase public function tearDown(): void { Mockery::close(); - User::truncate(); - Book::truncate(); - Item::truncate(); - Role::truncate(); - Client::truncate(); - Group::truncate(); - Photo::truncate(); } public function testEmbedsManySave() @@ -951,4 +938,36 @@ public function testGetQueueableRelationsEmbedsOne() $this->assertEquals(['father'], $user->getQueueableRelations()); $this->assertEquals([], $user->father->getQueueableRelations()); } + + public function testUnsetPropertyOnEmbed() + { + $user = User::create(['name' => 'John Doe']); + $user->addresses()->save(new Address(['city' => 'New York'])); + $user->addresses()->save(new Address(['city' => 'Tokyo'])); + + // Set property + $user->addresses->first()->city = 'Paris'; + $user->addresses->first()->save(); + + $user = User::where('name', 'John Doe')->first(); + $this->assertSame('Paris', $user->addresses->get(0)->city); + $this->assertSame('Tokyo', $user->addresses->get(1)->city); + + // Unset property + unset($user->addresses->first()->city); + $user->addresses->first()->save(); + + $user = User::where('name', 'John Doe')->first(); + $this->assertNull($user->addresses->get(0)->city); + $this->assertSame('Tokyo', $user->addresses->get(1)->city); + + // Unset and reset property + unset($user->addresses->get(1)->city); + $user->addresses->get(1)->city = 'Kyoto'; + $user->addresses->get(1)->save(); + + $user = User::where('name', 'John Doe')->first(); + $this->assertNull($user->addresses->get(0)->city); + $this->assertSame('Kyoto', $user->addresses->get(1)->city); + } }