-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Make blog post titles unique #1062
Conversation
src/Entity/Post.php
Outdated
use Symfony\Component\Validator\Constraints as Assert; | ||
|
||
/** | ||
* @ORM\Entity(repositoryClass="App\Repository\PostRepository") | ||
* @ORM\Table(name="symfony_demo_post") | ||
* @UniqueEntity(fields={"slug"}, errorPath="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.
Yes, the slug
value is generated after $form->isValid()
(when the validation process is fired) in Admin\BlogController.php
.
To make it work properly we can move this statement $post->setSlug(Slugger::slugify($post->getTitle()))
before $form->isValid()
and after $form->handleRequest($request)
. What do you think?
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.
Yes! That must be the error.
However, if I move that line ... I see this error:
Argument 1 passed to Symfony\Component\String\Slugger\AsciiSlugger::slug() must be of the type string, null given.
If I change it like this:
$form->handleRequest($request);
if ($form->isSubmitted()) {
$post->setSlug($slugger->slug($post->getTitle())->lower());
}
if ($form->isSubmitted() && $form->isValid()) {
// ...
}
Then I can again create multiple blog posts with the same slug, so the validation is not working.
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.
@javiereguiluz, Calling isValid()
method doesn't trigger validation. See https://github.com/symfony/form/blob/098f87036aeae1a1f4658d5f9f154b8cca628eb9/Form.php#L739
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 for the confusion, @voronkovich is right, is the $form->handleRequest()
who fires the validation process, so we're at the beginning again :)
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.
@javiereguiluz, @yceruto I would suggest to use a form event listener:
->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
$post = $event->getData();
$post->setSlug($this->slugger->slug($post->getTitle())->lower());
})
This also will decrease code duplicity, because we won't need to generate slug in both new
and edit
controllers.
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.
What about a custom validation by using the repositoryMethod
option of the @UniqueEntity()
annotation?
There we might have the chance to build the slug before checking that it's unique.
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.
This line $post->setSlug($this->slugger->slug($post->getTitle())->lower());
is unsafe, you'll need to check before that that the title value is not null. But yes, that's another option.
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 liked both solutions a lot. I think they are both equally correct. However, I decided to try the form event solution proposed by @voronkovich because it felt more closely related to Symfony. A repository is a Doctrine thing, not a strictly Symfony thing and that's why I think we should use form events in this case. But I'm open to hear other opinions and change this. Thanks!
@javiereguiluz, should we add a functional test for this feature? |
This PR was merged into the master branch. Discussion ---------- Make blog post titles unique I'm trying to fix #1045. We should make the `slug` unique because it's what we use to look for blog posts in the database. However, I can't make this work. If I define `UniqueEntity` on `title`, it works ... but if I define it on `slug`, it doesn't work (I can create any number of posts with the same slug). Anybody sees the error? Thanks! Commits ------- 178e2b1 Added a functional test 7486dc8 Added a form event to set the slug a4a316a Make blog post titles unique
I'm trying to fix #1045.
We should make the
slug
unique because it's what we use to look for blog posts in the database. However, I can't make this work. If I defineUniqueEntity
ontitle
, it works ... but if I define it onslug
, it doesn't work (I can create any number of posts with the same slug). Anybody sees the error? Thanks!