Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix attributeToArray method #3024

Closed

Conversation

florianJacques
Copy link
Contributor

@florianJacques florianJacques commented Jul 2, 2024

  • Fix model serialization, when model has embed relation or nested fields.

When dealing with embedded models with relationships (EmbedOne and/or EmbedMany), the serialization methods do not serialize Mongo BSON types in nested fields, as the function only converts top-level attributes.

In the exemple, prices is embedMany Relationship

 public function prices(): EmbedsMany
 {
      return $this->embedsMany(Price::class, 'prices', 'product');
 }

Before fix =>

 [
    "_id" => "667be7212ea8e4cc8b0dd636",
    "isActive" => true,
    "name" => "CREDIT_PACKAGE_3",
    "category" => "CREDIT_BALANCE",
    "quantity" => 3.0,
    "prices" => [
      [
        "currency" => "EUR",
        "price" => 5.99,
        "_id" => MongoDB\BSON\ObjectId {#4456
          +"oid": "667be7212ea8e4cc8b0dd634",
        },
      ],
    ],
]

After fix =>

 [
    "_id" => "667be7212ea8e4cc8b0dd636",
    "isActive" => true,
    "name" => "CREDIT_PACKAGE_3",
    "category" => "CREDIT_BALANCE",
    "quantity" => 3.0,
    "prices" => [
      [
        "currency" => "EUR",
        "price" => 5.99,
        "_id" => "667be7212ea8e4cc8b0dd634",
      ],
    ],
]

@florianJacques florianJacques requested a review from a team as a code owner July 2, 2024 13:58
@GromNaN GromNaN requested review from GromNaN and removed request for alcaeus July 2, 2024 15:32
@GromNaN
Copy link
Member

GromNaN commented Jul 2, 2024

Thank you @florianJacques for contributing. To review your PR correctly, I need that you describe the issue, and if possible add tests validating the fix.

@GromNaN GromNaN added this to the 4.6 milestone Jul 2, 2024
@florianJacques
Copy link
Contributor Author

Thank you @florianJacques for contributing. To review your PR correctly, I need that you describe the issue, and if possible add tests validating the fix.

Test ok

Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new test does not cover the issue, it works without your fix.

In order to convert date objects nested into embedded object (not embedded model), you can define a regular cast using a dot for the field path.

Example:

protected $casts = [
'birthday' => 'datetime',
'entry.date' => 'datetime',
'member_status' => MemberStatus::class,
];

Validated by this test:

// Test with create and array property
$user = User::create(['name' => 'Jane Doe', 'entry' => ['date' => $date]]);
$this->assertInstanceOf(Carbon::class, $user->getAttribute('entry.date'));

tests/EmbeddedRelationsTest.php Outdated Show resolved Hide resolved
@@ -328,12 +328,22 @@ 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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a private method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok now is split

Copy link
Contributor Author

@florianJacques florianJacques Jul 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the test, I simply reused existing model. Would you like me to create a new one?
Yes for nested fields (with no embed relationship), but will it work without my patch for more deep level fields?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you can create a new model class for the test.

florianJacques and others added 2 commits July 2, 2024 23:48
src/Eloquent/Model.php Outdated Show resolved Hide resolved
Co-authored-by: Jérôme Tamarelle <jerome@tamarelle.net>
Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking of rejecting your proposal.

Embeds should not be used in this way. Instead of calling $results['addresses'], you need to call $addresses->addresses()->get() which returns a collection of Address objects by applying the castings defined in the Model.

You can also work with objects directly, in which case they are not embedded and don't automatically have an id, but you can add one.

tests/EmbeddedRelationsTest.php Show resolved Hide resolved
$value = (string) $value;
} elseif ($value instanceof Binary) {
$value = (string) $value->getData();
} elseif ($value instanceof UTCDateTime) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think dates should be handled here. They were not in the current code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, indeed if relationships are called, casts are automatic. Sorry for the misunderstanding.
You can reject the fix proposal. Looking forward to contributing on something else.

@GromNaN GromNaN closed this Jul 4, 2024
@florianJacques florianJacques deleted the fix-modelSerialization branch July 4, 2024 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants