-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Fix incorrect behaviour when comparing castable attributes in originalIsEquivalent
method
#3439
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
Open
guram-vashakidze
wants to merge
6
commits into
mongodb:5.x
Choose a base branch
from
guram-vashakidze:5.x
base: 5.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+101
−0
Open
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
c6147c9
Fix overwriting `updated_at` when `$set` is used
guram-vashakidze 74d2cb5
Merge branch 'mongodb:5.x' into 5.x
guram-vashakidze f027089
fix incorrect behaviour when comparing castable attributes in `origin…
guram-vashakidze 40ecfd0
fix phpDoc return type
guram-vashakidze 8e808a3
comparing castable attributes just by serialization
guram-vashakidze 13d48d4
add one more "assert" into tests
guram-vashakidze File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MongoDB\Laravel\Tests\Models; | ||
|
||
class Options | ||
{ | ||
private string $option1; | ||
private string $option2; | ||
guram-vashakidze marked this conversation as resolved.
Show resolved
Hide resolved
guram-vashakidze marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public function setOption1(string $option1): self | ||
{ | ||
$this->option1 = $option1; | ||
return $this; | ||
} | ||
|
||
public function setOption2(string $option2): self | ||
{ | ||
$this->option2 = $option2; | ||
return $this; | ||
} | ||
|
||
public function serialize(): object | ||
{ | ||
$result = []; | ||
if (isset($this->option1)) { | ||
$result['option1'] = $this->option1; | ||
} | ||
|
||
if (isset($this->option2)) { | ||
$result['option2'] = $this->option2; | ||
} | ||
|
||
return (object) $result; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MongoDB\Laravel\Tests\Models; | ||
|
||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class OptionsCast implements CastsAttributes | ||
{ | ||
public function get(Model $model, string $key, mixed $value, array $attributes): Options | ||
{ | ||
$attributes = new Options(); | ||
if (! empty($value['option1'])) { | ||
$attributes->setOption1($value['option1']); | ||
} | ||
|
||
if (! empty($value['option2'])) { | ||
$attributes->setOption2($value['option2']); | ||
} | ||
|
||
return $attributes; | ||
} | ||
|
||
/** | ||
* @param Model $model | ||
* @param string $key | ||
* @param Options|null $value | ||
* @param array $attributes | ||
* | ||
* @return null[]|object[] | ||
*/ | ||
public function set(Model $model, string $key, mixed $value, array $attributes): array | ||
{ | ||
return [ | ||
$key => $value?->serialize(), | ||
]; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you checking the result of
serialize
here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because of using
===
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's what I suspected. Using
serialize
is not the right way to go about this. See my comment above about using==
when comparing objects. Strictly speaking you should be comparing the BSON representation, but since that's not always easily possible I think a loose object comparison (which will leverage a class'compare_objects
handler) is a safe middle ground.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, not sure I understood correctly, but why serialization is not right way here, can you explain a bit more, pls.
Example from your previous thread works correct. I guess there is even possible to leave just serialization. This example also working correctly:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
===
is an identity check, meaning that values have to be identical. For scalar values this works fine, but it breaks down for objects as PHP will compare the internal object IDs as you've shown in the previous example.==
is an equality check, meaning there is some advanced comparison logic happening for objects. For objects that have acompare_objects
handler implemented (which can only be done for internal classes such asMongoDB\BSON\Binary
, it will call the first handler it finds (first checking the object on the left side of the operation, then that on the right) and return that result. If there is nocompare_objects
handler, it falls back to a property equality check for objects of the same class and returnsfalse
when the objects are of different classes.This equality check is what we want here -- loosely speaking, when two values are equal (ignoring PHP's type coercion shenanigans around numeric strings) we can assume that they will map to the same representation in the database.
serialize
is an unnecessary complication at that point.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The theory of differences
==
/===
i know but with all due respect to your work and your knowledge, I cannot agree with you thatserialize
is unnecessary complication. What you described much more complicate for me... at first check both values is scalar or no, next compare this values by===
. If it's not scalar - compare objects==
. In most cases first compare will work. As I said before the easiest way here - leave just serialization (even remove firstif
) which will work as expected for all types. Also comparing objects trough serialization is giving us feature to affect compare behaviour (not sure how it can be used :D).It's just my thought, you're deciding is it respond your repo paradigm or no 🤝
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alcaeus I left comparing just by serialization. I faced an issue with comparing after
castAttribute
. The root in Laravel here. When I'm getting result fromcastAttribute
the result the same for$original
and for$attribute
in every cases.