-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DoctrineBridge][Validator] Allow validating every class against unique entity constraint #38662
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
Conversation
src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
Outdated
Show resolved
Hide resolved
The only not successful check is about the PHP attributes code syntax. I can't fix it. |
} | ||
} | ||
|
||
$class = $em->getClassMetadata(\get_class($entity)); | ||
try { | ||
$repository = $em->getRepository($entityClass); |
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.
Shouldn't we use $constraint->entityClass
here if possible?
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.
I need to check if the object being validated is an entity.
The $constraint->entityClass
always have an entity class.
Maybe I could change $entityClass
to $objectClass
? After all I changed @param object $entity
to @param object $object
.
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.
$entityClass = $constraint->entityClass ?? \get_class($object);
What I mean is couldn't we simply update line 67 to something like this and then use $entityClass
in the rest of the method?
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.
Ok, I could do it like that, but I also need to know if the object being validated is an entity.
This knowledge is useful in line 104. The error is related to the entity inheritance case and the helpful message, like
The "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity" entity repository does not support the "Symfony\Bridge\Doctrine\Tests\Fixtures\Person" entity. The entity should be an instance of or extend "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleStringIdEntity".
.
So I would change line 88 to $repository = $em->getRepository(\get_class($object));
. I hope it won't affect any older tests. Which I didn't want to change.
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.
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.
In this block, for simplicity, we should ONLY try to determine $isEntity
. By also trying to set $repository
, I think it confuses things. I would:
try {
$em->getRepository($value::class);
$isEntity = true;
} catch (ORMMappingException|PersistenceMappingException) {
$isEntity = false;
}
Or would this be enough?
$isEntity = $em->contains($value::class)?
Also, calling thex variable $isObjectEntity
or $isValueEntity
might be even more clear :)
Then, get the $repository
always below this.
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.
I don't remember why I didn't use contains 3 years ago. During the weekend I will check it on real examples, not interfaces.
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.
Cool - thanks :). And more important for me is to ONLY set the $isEntity
variable in this block. Then move figuring out the $repository
until later... ideally moving all of the logic for getting the repository back the bottom - https://github.com/symfony/symfony/pull/38662/files#diff-fd1785451fbb1d6abe41ae644ddbe7b39b6f03f3ba31f7ce07a18ef376e61293L130 - as that would greatly reduce the diff. I'm a little obsessed with reducing the diff on this PR just because with the current set of changes, it's really hard to see & understand what's changed. It may turn out that the diff DOES need to be large like this, but I'm hoping we can shrink it down by avoiding unnecessary code movement. That'd make the PR much easier to merge 👍
src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
Outdated
Show resolved
Hide resolved
d98262a
to
1053a55
Compare
Hi @derrabus, after reading the conversation, I'm not sure should I fix those Psalm errors. If it should be fixed, should it be part of this PR or should be fixed in all affected constraints? Also, should it be applied to branch 5.2, if we want branch 4.4 to remain stable? P.S. |
Psalm's complaint is valid: we should not change the name of a parameter declared by an interface when implementing that interface. Yet, we do this already and this of course is not your fault. However I don't think we should now pick another name that differs from the upstream declared one.
Fabbot currently reports two problems. One of them is valid. 😉 |
This PR changed it from the
Ye, I only added the blank line to trigger Travis and see if Fabbot already uses the new version of PHP-CS-Fixer. I don't see any button (in Github UI) to run the tests again or info what version of PHP-CS-Fixer, Fabbot use. |
No, I wouldn't backport the parameter name change.
Just remove that extra line again and don't mind the |
In 2021 carsonbot removed [Validator] from the title. Now we are back to the original title :). |
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.
Let's get this into 7.1!
Fixed merge conflict. Commit was the reason |
Can you please rebase (and squash while doing so)? We don't merge PRs with merge commits in them. |
@nicolas-grekas So that there are no misunderstandings. |
I guess the UI doesn't help, I never use it myself. |
ok, I'll do it later today |
…ue entity constraint
Done |
@nicolas-grekas @kbond |
Thank you @wkania. |
…ss against unique entity constraint (wkania) This PR was merged into the 7.1 branch. Discussion ---------- [DoctrineBridge][Validator] Allow validating every class against unique entity constraint | Q | A | ------------- | --- | Branch? | 7.x <!-- see below --> | Bug fix? | no | New feature? | yes <!-- pleasedate src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | Fix #22592 | License | MIT | Doc PR | symfony/symfony-docs#14458 <!-- required for new features --> Yet another try to allow validating every class against unique entity constraint. Based on the knowledge from issue #22592 and pull request #24974. This constraint doesn’t provide any protection against race conditions, which is enough in most cases. You can always try-catch flush method. Let's not talk about this problem. Current state: - can be applied only to an entity, - support entity inheritance, - can validate unique combinations of multiple fields, - meaningful errors related to entities, - is valid during an update, when the only matched entity is the same as the entity being validated New state: - preserve the current state, - all old tests pass (no changes in them), - no breaking changes, - can be applied to any class (like DTO), - can map object fields to entity fields (optional), - when the object update some entity, there is an option to provide the identifier field names to match that entity (optional) Examples: 1. DTO adds a new entity. ``` namespace App\Message; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * `@UniqueEntity`(fields={"name"}, entityClass="App\Entity\User") */ class HireAnEmployee { public $name; public function __construct($name) { $this->name = $name; } } ``` 2. DTO adds a new entity, but the name of the field in the entity is different. ``` namespace App\Message; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * `@UniqueEntity`(fields={"name": "username"}, entityClass="App\Entity\User") */ class HireAnEmployee { public $name; public function __construct($name) { $this->name = $name; } } ``` 3. DTO updates an entity. ``` namespace App\Message; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; /** * `@UniqueEntity`(fields={"name"}, entityClass="App\Entity\User", identifierFieldNames={"uid": "id"}) */ class UpdateEmployeeProfile { public $uid; public $name; public function __construct($uid, $name) { $this->uid = $uid; $this->name = $name; } } ``` Commits ------- adb9afa [DoctrineBridge][Validator] Allow validating every class against unique entity constraint
Closing (it has been merged but due to a race condition, it has not been marked as merged) |
…ject (HypeMC) This PR was merged into the 7.1 branch. Discussion ---------- [DoctrineBridge] Fix `UniqueEntityValidator` with proxy object | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #57075 | License | MIT Before #38662, `$fieldValue = $class->reflFields[$fieldName]->getValue($entity);` was used to get the value of a property, so it makes sense to keep using it when the object is an entity. Commits ------- 99f279b [DoctrineBridge] Fix `UniqueEntityValidator` with proxy object
Yet another try to allow validating every class against unique entity constraint.
Based on the knowledge from issue #22592 and pull request #24974.
This constraint doesn’t provide any protection against race conditions, which is enough in most cases. You can always try-catch flush method. Let's not talk about this problem.
Current state:
New state:
Examples: