From 678709b80dfb452e4ea0f4cabe8423821864b431 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Tue, 2 Jul 2024 15:55:07 +0200 Subject: [PATCH 1/6] fix attributeToArray method --- src/Eloquent/Model.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index f7b4f1f36..e850dded5 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -328,12 +328,20 @@ public function attributesToArray() // MongoDB related objects to a string representation. This kind // of mimics the SQL behaviour so that dates are formatted // nicely when your models are converted to JSON. - foreach ($attributes as $key => &$value) { + $convertMongoObjects = function (&$value) use (&$convertMongoObjects) { if ($value instanceof ObjectID) { $value = (string) $value; } elseif ($value instanceof Binary) { $value = (string) $value->getData(); + } elseif (is_array($value)) { + foreach ($value as &$embedValue) { + $convertMongoObjects($embedValue); + } } + }; + + foreach ($attributes as $key => &$value) { + $convertMongoObjects($value); } return $attributes; From 6403bd8aee0aad32d3c7f84ba8bf0b99a334763a Mon Sep 17 00:00:00 2001 From: florianJacques Date: Tue, 2 Jul 2024 16:36:49 +0200 Subject: [PATCH 2/6] Add BSON UTCDateTime serialization --- src/Eloquent/Model.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index e850dded5..f898fd534 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -333,6 +333,8 @@ public function attributesToArray() $value = (string) $value; } elseif ($value instanceof Binary) { $value = (string) $value->getData(); + } elseif ($value instanceof UTCDateTime) { + $value = $this->serializeDate($value->toDateTime()); } elseif (is_array($value)) { foreach ($value as &$embedValue) { $convertMongoObjects($embedValue); From ed5a9dbe5afc4e33f02897fa2b25b391d8177ac4 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Tue, 2 Jul 2024 18:15:16 +0200 Subject: [PATCH 3/6] Add tests --- tests/EmbeddedRelationsTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/EmbeddedRelationsTest.php b/tests/EmbeddedRelationsTest.php index 2dd558679..b87bf84f6 100644 --- a/tests/EmbeddedRelationsTest.php +++ b/tests/EmbeddedRelationsTest.php @@ -19,6 +19,7 @@ use MongoDB\Laravel\Tests\Models\User; use function array_merge; +use function PHPUnit\Framework\assertIsString; class EmbeddedRelationsTest extends TestCase { @@ -945,4 +946,13 @@ public function testGetQueueableRelationsEmbedsOne() $this->assertEquals(['father'], $user->getQueueableRelations()); $this->assertEquals([], $user->father->getQueueableRelations()); } + + public function testEmbedManySerialization() + { + $user = User::create(['name' => 'John Doe']); + $user->addresses()->save(new Address(['city' => 'New York'])); + + $results = $user->toArray(); + assertIsString($results['addresses'][0]['_id']); + } } From 460f5488b86b109cc742fadec8c2c8a1ab332498 Mon Sep 17 00:00:00 2001 From: Jacques Florian Date: Tue, 2 Jul 2024 23:48:33 +0200 Subject: [PATCH 4/6] Update tests/EmbeddedRelationsTest.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jérôme Tamarelle --- tests/EmbeddedRelationsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/EmbeddedRelationsTest.php b/tests/EmbeddedRelationsTest.php index b87bf84f6..601c8c368 100644 --- a/tests/EmbeddedRelationsTest.php +++ b/tests/EmbeddedRelationsTest.php @@ -953,6 +953,6 @@ public function testEmbedManySerialization() $user->addresses()->save(new Address(['city' => 'New York'])); $results = $user->toArray(); - assertIsString($results['addresses'][0]['_id']); + $this->assertIsString($results['addresses'][0]['_id']); } } From 1e494b6a9cd6d896a7df9dc364dd948724395842 Mon Sep 17 00:00:00 2001 From: florianJacques Date: Wed, 3 Jul 2024 00:16:14 +0200 Subject: [PATCH 5/6] split conversion function, and change test --- src/Eloquent/Model.php | 45 +++++++++++++++++++++------------ tests/EmbeddedRelationsTest.php | 11 +++++--- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index f898fd534..f01373303 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -319,31 +319,44 @@ protected function fromDecimal($value, $decimals) return new Decimal128($this->asDecimal($value, $decimals)); } + /** + * Convert MongoDB objects to their string representations. + * + * This method converts MongoDB related objects (ObjectID, Binary, UTCDateTime) + * to their serialized representations, ensuring the values can be correctly + * serialized when the model is converted to JSON. + * + * @param mixed $value The value to convert + * + * @return mixed + */ + protected function convertMongoObjects(mixed $value): mixed + { + if ($value instanceof ObjectID) { + $value = (string) $value; + } elseif ($value instanceof Binary) { + $value = (string) $value->getData(); + } elseif ($value instanceof UTCDateTime) { + $value = $this->serializeDate($value->toDateTime()); + } elseif (is_array($value)) { + foreach ($value as &$nestedValue) { + $nestedValue = $this->convertMongoObjects($nestedValue); + } + } + + return $value; + } + /** @inheritdoc */ public function attributesToArray() { $attributes = parent::attributesToArray(); - // Because the original Eloquent never returns objects, we convert // MongoDB related objects to a string representation. This kind // of mimics the SQL behaviour so that dates are formatted // nicely when your models are converted to JSON. - $convertMongoObjects = function (&$value) use (&$convertMongoObjects) { - if ($value instanceof ObjectID) { - $value = (string) $value; - } elseif ($value instanceof Binary) { - $value = (string) $value->getData(); - } elseif ($value instanceof UTCDateTime) { - $value = $this->serializeDate($value->toDateTime()); - } elseif (is_array($value)) { - foreach ($value as &$embedValue) { - $convertMongoObjects($embedValue); - } - } - }; - foreach ($attributes as $key => &$value) { - $convertMongoObjects($value); + $value = $this->convertMongoObjects($value); } return $attributes; diff --git a/tests/EmbeddedRelationsTest.php b/tests/EmbeddedRelationsTest.php index 601c8c368..d4d54bd48 100644 --- a/tests/EmbeddedRelationsTest.php +++ b/tests/EmbeddedRelationsTest.php @@ -19,7 +19,6 @@ use MongoDB\Laravel\Tests\Models\User; use function array_merge; -use function PHPUnit\Framework\assertIsString; class EmbeddedRelationsTest extends TestCase { @@ -34,6 +33,7 @@ public function tearDown(): void Client::truncate(); Group::truncate(); Photo::truncate(); + Address::truncate(); } public function testEmbedsManySave() @@ -949,10 +949,13 @@ public function testGetQueueableRelationsEmbedsOne() public function testEmbedManySerialization() { - $user = User::create(['name' => 'John Doe']); - $user->addresses()->save(new Address(['city' => 'New York'])); + $address = new Address(['country' => 'France']); + $address->save(); + + $address->addresses()->create(['city' => 'Paris']); + $address->addresses()->create(['city' => 'Nice']); - $results = $user->toArray(); + $results = $address->toArray(); $this->assertIsString($results['addresses'][0]['_id']); } } From 0bbb1addc718e82761587588fcf408244b65a372 Mon Sep 17 00:00:00 2001 From: Jacques Florian Date: Thu, 4 Jul 2024 11:17:08 +0200 Subject: [PATCH 6/6] Update src/Eloquent/Model.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jérôme Tamarelle --- src/Eloquent/Model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index f01373303..b9f87e1ad 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -352,6 +352,7 @@ public function attributesToArray() { $attributes = parent::attributesToArray(); + // Because the original Eloquent never returns objects, we convert // MongoDB related objects to a string representation. This kind // of mimics the SQL behaviour so that dates are formatted // nicely when your models are converted to JSON.