-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[DoctrineBridge] Add a way to select the repository used by the UniqueEntity validator #15002
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
|
||
if (!($supportedClass === $className || is_subclass_of($className, $supportedClass))) { | ||
throw new ConstraintDefinitionException(sprintf( | ||
"Unable to use the given '%s' repository for the '%s' entity.", |
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 Symfony, we are quoting with "
instead of '
.
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 must have done the same as here I guess.
There are some other occurrences of "bad" quoting messages in Symfony components.
Anyway, fixed. :)
This PR was merged into the 2.3 branch. Discussion ---------- Fix quoting style consistency. | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This is a really minor change with reference to [this comment](#15002 (comment)). If it's fine, [those changes](symfony:2.7...ogizanagi:fix_quoting_style/2.7) for 2.7 will follow up too. Commits ------- 57d30f9 Fix quoting style consistency.
Hey, I also hit this bug, very similar use case too... I was in the process of developing a new PR to fix it... However, I had a slightly different approach in mind, and thought it would be nice to have your feedback regarding this. If you feel like this should be in a separate PR, please, just say so. I will remove my comment and submit it as a separate [RFC] issue. If you’re interested, thank you very much, however (disclaimer) brace yourself, it’s a rather long post! 😉 PS: Shortcut: I created a RFC (#16969) issue and two PRs (#16978, #16981) to provide a better understanding of my design. If you checked these, you can skip this post entirely. SuggestionOn the naming things is hard front, I was thinking about using I was actually thinking it could be an information many Class Constraints could need. So I was thinking of moving this outside of the Doctrine Bridge and inside the Validator Component itself. I thought we could create a new Regarding the UniqueEntity Validator, we would, then, use the Constraint ‘s DiscussionI think it would provide a more generic approach (any constraint implementing the Interface could get access to its target). This is moreover seamless for the user. TransitionAs a transitory method, in case the loader isn't patched yet (or if the StaticMethodLoader is used and the target is not provided). The Validator could fallback to the FlexibilityOn the other hand, I can see two slight reductions of flexibility in my approach compared to yours: BehaviourFirst, the behaviour, which could be one of
Separation between Validated Entities and Target RepositorySecond, my solution doesn’t allow to apply the Constraint on Class A, while targeting instances of Class B (which would be somewhere else in the hierarchy). This covers both an explicit I see three possibilities for this combinaison:
IMO, these are not deep issues, If you feel like a long(er) read, here is a detailed analysis of each case, otherwise, you might want to skip the next couple of paragraphs... In the first case (B is outside the inheritance line of A), it would mean that Students cannot have names used by Teachers, but the other way around wouldn’t be an issue. Additional care is required to ensure Students already existing do not conflict with a new Teacher name. This is a blacklisting semantic. While useful, we could argue this semantic isn’t covered by In the second case (B is a child class of A), it would mean that Persons cannot have names already used by Students, but names used by Teachers would be OK. This is very similar to the previous case and seems to carry the same Blacklisting semantic. Therefore, it falls outside of In the third and last case (B is a child class of A), it would mean that Teachers can have duplicated names, but Students can’t have duplicated names, nor the same name as Teachers. Although the first part of Students’ restrictions seems to be matching the Multiple Table inheritanceIn the case of Multiple Table inheritance, there are a few cases where the current implementation may not crash, since the UNIQUE Index may prove impossible to generate (if the field is represented differently in some subclasses). This would be another very similar bug. One might argue this to be a border-line use. If what we need is a per-table UniqueEntity behavior (similar to what separate UNIQUE Indices on separate tables would enforce), this should be enforced by using separate If what we need is an actual cross-table ConclusionWhat do you think? I know it's a bit of a complex implementation, but the code should be relatively simple and modular. I'm sorry to hijack your PR, but granted we both aim to solve the same issue I thought it would be a better idea to run it by you first. Again, if you think it should be in its own issue, don’t hesitate to tell me so and I’ll extract it from here. There is also the issue of which solution would be prefered by symfony/deciders. Thanks for taking the time to read all that if you did. It’s rather long and a bit tedious if I may say so myself. Anyway, all feedback will be welcomed and I hope both our solutions could be seen as complementary. |
@lemoinem Hey ! Very nice and well-written comment to expose your idea.
Don't worry. Please, submit a PR if you're confident enough. symfony/deciders will take a decision more easily and it'll give a new visibility to this issue. IMO, it's important, as it is kind of a "bug fix" but requires a feature implementation, and we're one month to the feature freeze. Also, as a side note to my own PR, I actually think the |
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
@ogizanagi Thank you very much for the feedback. I created a RFC (#16969) issue and two PRs (#16978, #16981) to provide a better understanding of my design. We'll just have to wait for @symfony/deciders to check on which is chosen ;) |
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
Fixes symfony#16969 Fixes symfony#4087 Fixes symfony#12573 Incompatible with symfony#15002 Incompatible with symfony#12977
What's the status of this PR? |
@fabpot : @lemoinem's work in #16978 and #16981 looks promising to me, but I'm not sure about the need to expose this new "target aware constraint" feature if the only use case mentioned until now is about solving the "UniqueEntityConstraint with inheritance" issue (#12573, #4087). On the other hand, I'm not satisfied by the new |
$supportedClass = $repository->getClassName(); | ||
|
||
if (!($entity instanceof $supportedClass)) { | ||
throw new ConstraintDefinitionException(sprintf('The "%1$s" entity repository does not support the "%2$s" entity. The entity should be an instance of or extend "%1$s".', $constraint->repository, $class->getName())); |
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.
- sprintf('The "%1$s" entity repository does not support the "%2$s" entity. The entity should be an instance of or extend "%1$s".', $constraint->repository, $class->getName())
+ sprintf('The "%s" entity repository does not support the "%s" entity. The entity should be an instance of or extend "%s".', $constraint->repository, $class->getName(), $supportedClass)
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.
indeed
@fabpot Did you (or anyone else from the core team), had time to take a look at theses PRs? It would help if we at least knew which direction is favored. Both implementations are pretty much in a final state (short of rebasing them), and if neither is deemed good enough, a middle ground will surely be reached as @ogizanagi and I have already been collaborating on this. The critical element we need right now would be feedback. Sorry for the direct ping, but the issue is quite problematic, once one hit it... |
Thanks for the ping. Sorry, but I'm no Doctrine expert, so someone else from @symfony/deciders should probably review this one and give you some feedback. @HeahDude might have some opinions as well. I would of course be more than happy to merge this whenever we think this is "good enough" as you wrote. |
👍 but @chalasr's comment should be taken into account. |
$repository = $em->getRepository($constraint->repository); | ||
$supportedClass = $repository->getClassName(); | ||
|
||
if (!($entity instanceof $supportedClass)) { |
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 parentheses can be removed here
@@ -26,6 +26,7 @@ class UniqueEntity extends Constraint | |||
public $message = 'This value is already used.'; | |||
public $service = 'doctrine.orm.validator.unique'; | |||
public $em = null; | |||
public $repository = null; |
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.
If I understand correctly, this is a class name of the entity related to the repository. So, repository
is misleading 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.
UniqueEntity constraints --> why not simply $class
(i.e. entity class)
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.
Indeed, as I said, I was not satisfied by the name of this option. If you think $class
is a better candidate, let's do it. 👍
I did not use this name at first because the idea is to select and fix the repository to use for the UniqueEntity
constraint, and I thought at the moment it could be misleading as well to have a class
option when you already set this constraint on an entity (useRepositoryOf="Person"
was probably conveying this idea better, but is an hideous name 😅 ).
Thank you guys for the feedbacks. I'll update this PR very soon. :) |
@xabbuh #15002 (comment) is part of the main reason I came up with my proposal. Having the Constraint extracting "itself" (implicitly) the repository to use seemed ... cleaner from a design F438 standpoint. Regarding the other use cases for a ConstraintAware, I detailed a few examples in #16969, mostly the idea is to provide constraints validating an instance among the list of existing instances. Other self-referencing mechanisms, White/Blacklisting is the most obvious example. I am afraid I don't a concrete example on hands, and I understand the applications will be limited. If we could find a way to register implicitly the class the constraint has been declared on, without adding the complexities of my design. I'm sure it would make a great trade-off for this issue. With an explicit way to specify the repository, I'm afraid some might misuse the Constraint and bring around bigger issues regarding compatibility or clarity. At least, I would insist on adding a note in the documentation to that effect. |
So, I've rebased this branch on master and made the suggested fixes. I've also renamed the
Of course, the new option has to be documented at least on the UniqueEntity constraint page. Do you have some suggestions about what the user should be warned ? |
|
…iqueEntity validator The new option expects an entity path, in order to select its repository. This allows to properly use the UniqueEntity constraint on hierarchical (inheritance) entities, using the root class repository in order to check the uniqueness, and not just the child repository.
@fabpot : I've submitted the PR on the documentation repository. I think this is ready. :) |
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.
Looks good to me 👍
Thank you @ogizanagi. |
…ed by the UniqueEntity validator (ogizanagi) This PR was merged into the 3.2-dev branch. Discussion ---------- [DoctrineBridge] Add a way to select the repository used by the UniqueEntity validator | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #12573, #4087, #12977 | License | MIT | Doc PR | symfony/symfony-docs#7057 This is a cherry pick of #12977 on ~~2.8~~ 3.2 branch, as it is clearly a new feature, even if it was primary introduced in order to fix an inappropriate behavior that might be considered as a bug. Commits ------- 00d5459 [Doctrine] [Bridge] Add a way to select the repository used by the UniqueEntity validator
…(ogizanagi) This PR was merged into the master branch. Discussion ---------- [DoctrineBridge] Document the new `entityClass` option Waiting for symfony/symfony#15002 to be merged. Commits ------- a9c2fc2 [DoctrineBridge] Document the new `entityClass` option
This is a cherry pick of #12977 on
2.83.2 branch, as it is clearly a new feature, even if it was primary introduced in order to fix an inappropriate behavior that might be considered as a bug.