Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Symfony4] Problème validation champ Unique

Integrity constraint violation FOSUserBundle

    22 mai 2018 à 20:39:09

    Bonjour à tous,

    Je viens vers vous car celà fais plusieurs jours que j'essaie d'overrider FosUserBundle pour rajouter une clé pour pouvoir s'enregistrer, mais bref passons ceci n'est pas important.

    Ce que je souhaite faire touche presque à la fin sauf que je me heurte à un problème. J'ai voulu mettre une contrainte sur l'email pour mes User mais lors de l'envoie du formulaire la contrainte n'est pas pris en compte, ce qui a pour effet de me remonter une exception.

    An exception occurred while executing 'INSERT INTO user (username, username_canonical, email, email_canonical, enabled, salt, password, last_login, confirmation_token, password_requested_at, roles) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params ["Sorrow1114", "sorrow1114", "****@gmail.com", "****@gmail.com", 0, null, "$2y$13$OMsKqJktsTKo5yNZlVUppOMizTo6fcKbrZY\/nBYc66qXDSUO\/zxwm", null, "sR0-TB0ASzEehU6bHkilBzSfFMEp2NXl_cyHWpe9E0A", null, "a:0:{}"]:
    SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '****@gmail.com' for key 'UNIQ_8D93D649A0D96FBF'



    J'aimerais donc savoir si l'un d'entre vous avez déjà été confonté à cela ?

    Entity

    <?php
    
    namespace App\Entity;
    
    use FOS\UserBundle\Model\User as BaseUser;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    use Symfony\Component\Validator\Constraints as Assert;
    
    
    /**
     * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
     * @UniqueEntity(fields="emailCanonical", errorPath="email", message="fos_user.email.already_used", groups={"Registration", "Profile"})
     */
    class User extends BaseUser
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        protected $id;
    
        /**
         * @Assert\NotBlank()
         */
        protected $emailCanonical;
    
        /**
         * @ORM\OneToOne(targetEntity="App\Entity\RegistrationKey", mappedBy="user", cascade={"persist", "remove"})
         */
        protected $registrationKey;
    
        public function getId()
        {
            return $this->id;
        }
    
        public function getRegistrationKey(): ?RegistrationKey
        {
            return $this->registrationKey;
        }
    
        public function setRegistrationKey(?RegistrationKey $registrationKey): self
        {
            $this->registrationKey = $registrationKey;
    
            // set (or unset) the owning side of the relation if necessary
            $newUser = $registrationKey === null ? null : $this;
            if ($newUser !== $registrationKey->getUser()) {
                $registrationKey->setUser($newUser);
            }
    
            return $this;
        }
    }
    

    Controller

    <?php
    
    namespace App\Controller;
    
    use App\Entity\RegistrationKey;
    use App\Form\RegistrationKeyType;
    use App\Form\RegistrationType;
    use FOS\UserBundle\Event\FilterUserResponseEvent;
    use FOS\UserBundle\Event\FormEvent;
    use FOS\UserBundle\Event\GetResponseUserEvent;
    use FOS\UserBundle\FOSUserEvents;
    use Symfony\Component\HttpFoundation\RedirectResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    use FOS\UserBundle\Controller\RegistrationController as BaseController;
    
    /**
     * @Route(service="app.controller.register")
     */
    class RegistrationController extends BaseController
    {
        private $eventDispatcher;
        private $userManager;
        private $tokenStorage;
    
        public function __construct($serviceContainer = null)
        {
            $this->setContainer($serviceContainer);
            $this->eventDispatcher = $this->container->get('event_dispatcher');
            $this->userManager = $this->container->get('fos_user.user_manager');
            $this->tokenStorage = $this->container->get('security.token_storage');
        }
    
        /**
         * @Route("/preregister", name="preRegister")
         */
        public function preRegisterAction(Request $request)
        {
            $form = $this->createForm(RegistrationKeyType::class);
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {
                $registrationKey = $this->getDoctrine()->getManager()->getRepository(RegistrationKey::class)
                                        ->findBy(["key" => $form["key"]->getData()]);
                $keyExist = $registrationKey != null ? true : false;
                if ($keyExist) {
                    $this->get('session')->set("key", $registrationKey);
                    return $this->redirectToRoute('register');
                }
            }
            return $this->render('default/form.html.twig', array(
                'form'            => $form->createView(),
                'controller_name' => 'RegistrationController',
                'name'            => 'Key',
            ));
        }
    
    
        /**
         * @Route("/register", name="register")
         */
        public function registerAction(Request $request)
        {
            $key = $this->get('session')->get("key");
            if ($key == null) {
                return $this->redirectToRoute('preRegister');
            } else {
                $registrationKey = $this->getDoctrine()->getManager()->getRepository(RegistrationKey::class)
                                        ->findOneBy(["key" => $key[0]->getKey()]);
            }
            $user = $this->userManager->createUser();
            $user->setEnabled(true);
            $user->setRegistrationKey($registrationKey);
            dump($user);
    
            $event = new GetResponseUserEvent($user, $request);
            $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
    
            if (null !== $event->getResponse()) {
                return $event->getResponse();
            }
    
            $form = $this->createForm(RegistrationType::class, $user);
    
            $form->handleRequest($request);
    
            if ($form->isSubmitted()) {
                            if ($form->isValid()) {
                $event = new FormEvent($form, $request);
                $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
    
                $this->userManager->updateUser($user);
    
                if (null === $response = $event->getResponse()) {
                    $url = $this->generateUrl('fos_user_registration_confirmed');
                    $response = new RedirectResponse($url);
                }
    
                $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
    
                return $response;
                            }
    
                $event = new FormEvent($form, $request);
                $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
    
                if (null !== $response = $event->getResponse()) {
                    return $response;
                }
            }
    
            return $this->render('@FOSUser/Registration/register.html.twig', array(
                'form' => $form->createView(),
            ));
        }
    
    }
    

    Form

    <?php
    
    namespace App\Form;
    
    use App\Entity\User;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\Type\EmailType;
    use Symfony\Component\Form\Extension\Core\Type\PasswordType;
    use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
    use Symfony\Component\Form\Extension\Core\Type\SubmitType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    class RegistrationType extends AbstractType
    {
        /**
         * {@inheritdoc}
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('email', EmailType::class, array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
                ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
                ->add('plainPassword', RepeatedType::class, array(
                    'type'            => PasswordType::class,
                    'options'         => array(
                        'translation_domain' => 'FOSUserBundle',
                        'attr'               => array(
                            'autocomplete' => 'new-password',
                        ),
                    ),
                    'first_options'   => array('label' => 'form.password'),
                    'second_options'  => array('label' => 'form.password_confirmation'),
                    'invalid_message' => 'fos_user.password.mismatch',
                ))
                ->add('submit', SubmitType::class, array('label'              => 'registration.submit',
                                                         'translation_domain' => 'FOSUserBundle'));
        }
    
        /**
         * {@inheritdoc}
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class'    => User::class,
                'csrf_token_id' => 'registration',
            ));
        }
    
        // BC for SF < 3.0
    
        /**
         * {@inheritdoc}
         */
        public function getName()
        {
            return $this->getBlockPrefix();
        }
    
        /**
         * {@inheritdoc}
         */
        public function getBlockPrefix()
        {
            return 'fos_user_registration';
        }
    }
    

    Le code se trouve ici pour ceux qui serait intéresser : https://github.com/sanjuant/kitscreator

    Merci d'avance a ceux qui pourront m'éclairer.



    -
    Edité par Sorrow81 23 mai 2018 à 19:06:30

    • Partager sur Facebook
    • Partager sur Twitter
      23 mai 2018 à 18:28:06

      Change  le champs unique de ta column email de ta bdd ?
      • Partager sur Facebook
      • Partager sur Twitter
        23 mai 2018 à 18:35:16

        J'ai essayer de faire ma contrainte sur email aussi mais cela ne fonctionne pas. Le comportement par défault de FOSUserBundle sans override de la méthode fonctionne. Le formulaire de registration utilise par default formFactory mais dans mon cas cela ne fonctionne pas.

        class RegistrationController extends Controller
        {
            private $eventDispatcher;
            private $formFactory;
            private $userManager;
            private $tokenStorage;
        
            public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager, TokenStorageInterface $tokenStorage)
            {
                $this->eventDispatcher = $eventDispatcher;
                $this->formFactory = $formFactory;
                $this->userManager = $userManager;
                $this->tokenStorage = $tokenStorage;
            }
        
            /**
             * @param Request $request
             *
             * @return Response
             */
            public function registerAction(Request $request)
            {
                $user = $this->userManager->createUser();
                $user->setEnabled(true);
        
                $event = new GetResponseUserEvent($user, $request);
                $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
        
                if (null !== $event->getResponse()) {
                    return $event->getResponse();
                }
        
                $form = $this->formFactory->createForm();
                $form->setData($user);
        
                $form->handleRequest($request);
        
                if ($form->isSubmitted()) {
                    if ($form->isValid()) {
                        $event = new FormEvent($form, $request);
                        $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
        
                        $this->userManager->updateUser($user);
        
                        if (null === $response = $event->getResponse()) {
                            $url = $this->generateUrl('fos_user_registration_confirmed');
                            $response = new RedirectResponse($url);
                        }
        
                        $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
        
                        return $response;
                    }
        
                    $event = new FormEvent($form, $request);
                    $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
        
                    if (null !== $response = $event->getResponse()) {
                        return $response;
                    }
                }
        
                return $this->render('@FOSUser/Registration/register.html.twig', array(
                    'form' => $form->createView(),
                ));
            }

        J'ai donc utilisé mon propre formulaire.

        • Partager sur Facebook
        • Partager sur Twitter
          24 mai 2018 à 21:08:17

          Tu as trouvé la solution ?
          • Partager sur Facebook
          • Partager sur Twitter
            24 mai 2018 à 21:47:18

            Non toujours pas, j'ai essayer d'ovveride le formulaire par default de FOSUserBundle mais j'ai le même problème :/.
            • Partager sur Facebook
            • Partager sur Twitter

            [Symfony4] Problème validation champ Unique

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown