Symfony Check if user exist in database

10,802

Solution 1

You shouldn't need to do this in the controller. This is basic entity validation and Symfony comes with built in constraints to handle this sort of thing.

Assuming you are using a User Entity similar to below in your Symfony application you need only apply a unique validation constraint to the user class and specify which properties you want to test against for uniqueness. This example will validate that the user is unique by email, and throw an exception if not.

// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/** @UniqueEntity(
  * fields={"email"},
  * errorPath="email",
  * message="It appears you have already registered with this email."
  *)
  */
class User
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string $email
     *
     * @ORM\Column(name="email", type="string", length=255, unique=true)
     * @Assert\Email()
     */
    protected $email;

    // ...
}

Pay notice to the @UniqueEntity("email") annotation on the class and the use statements. Of course you'll need to adopt this logic to your user class.

// controller action
public function newAction(Request $request)
{
    $invite = new Invite();

    $form = $this->createForm(InviteType::class, $invite);

    if ($request->isMethod('POST')) {
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($invite);
            $em->flush();

            $this->get('app_mailer')->sendMailInscriptionMjml(
              $invite, $this->getParameter('client_mail_to')
            );

            $this->get('session')->getFlashBag()
              ->add('success', 'Votre inscription à été pris en compte.');

            return $this->redirect(
              $this->generateUrl(
                'invite_show', array(
                  'id' => $invite->getId()
                )
              )
            );
         }
    }

    return $this->render('@App/invite/new.html.twig', array(
        'invite' => $invite,
        'form' => $form->createView(),
    ));
}

For more on this:

https://symfony.com/doc/current/reference/constraints/UniqueEntity.html

Solution 2

// Pass in the entity manager to your form via options
// Do this before you call $this->createForm:
// $options['entityManager'] = $this->getDoctrine()->getManager();
// then call $form = $this->createForm(InviteType::class, $invite, $options);

// Inside your form type i.e. InviteType
$em = $options['entityManager'];

$builder->addEventListener(
    FormEvents::PRE_SUBMIT,
    function (FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();
        $user = $data['user']; // this needs to be whatever you called user in your form
        $userRepo = $em->getRepository('User'); // this needs to be the location of your user repository
        if ($userRepo->findOneBy(['user' => $user])) { // you need to pick a field that determines how you will search for the user via the repository
            $form->addError(new FormError('User already exists'));
        }
    }
);
Share:
10,802

Related videos on Youtube

Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin over 1 year

    I am looking for a solution in my controller to check before sending a form if the user already exists in the database. Here is my action on which I would like to implement this.

    /**
     * Creates a new invite entity.
     *
     * @Route("/inscription", name="invite_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request)
    {
        $invite = new Invite();
    
        $form = $this->createForm(InviteType::class, $invite);
    
        if ($request->isMethod('POST')) {
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {
                $em = $this->getDoctrine()->getManager();
                $em->persist($invite);
                $em->flush();
    
                $this->get('app_mailer')->sendMailInscriptionMjml($invite, $this->getParameter('client_mail_to'));
    
                $this->get('session')->getFlashBag()->add('success', 'Votre inscription à été pris en compte.');
            } else {
                $this->get('session')->getFlashBag()->add('error', 'Une erreur est survenue.');
            }
    
            return $this->redirect($this->generateUrl('invite_show', array('id' => $invite->getId())));
        }
    
        return $this->render('@App/invite/new.html.twig', array(
            'invite' => $invite,
            'form' => $form->createView(),
        ));
    }
    

    Thank you for your help

  • Admin
    Admin about 6 years
    I create my request directly in the controller or in the repository? thanks
  • wanderer0810
    wanderer0810 about 6 years
    You would run it as an SQL statement.
  • Admin
    Admin about 6 years
    I am trying to warn the user that he is already registered. Thanks
  • Robert Wade
    Robert Wade about 6 years
    you can do that with this set up. It's what its for.
  • Robert Wade
    Robert Wade about 6 years
    It validates that there are no other users with that email already in your database. Then throws the exception if it finds one. The point is, you don't have to write a query in your controller to do this. I've updated the annotation to show you can even include your own custom error message if you want.
  • Admin
    Admin about 6 years
    Thank you but I have nothing that appears in message on screen. I have to add something to my controller? Thank you
  • Robert Wade
    Robert Wade about 6 years
    it's hard for me to say without seeing your complete set up. This example assumes you have an "email" property on your Invite entity class, that you've set up the annotations correctly and are rendering your form properly in twig. Are you seeing an exception in your profiler?
  • Admin
    Admin about 6 years
    I put my controller on top and here is my twig
  • Robert Wade
    Robert Wade about 6 years
    it's best if you edit your original question and not keep posting changes to it as answers :) Have you added the validation constraint to your Invite entity? And the use statements? are you seeing errors in your profiler?
  • Admin
    Admin about 6 years
    Yes it's true forgive me. Yes I have added what you told me but I have no error in return except that it goes into the else of my controller.
  • Robert Wade
    Robert Wade about 6 years
    you should be able to get rid of that else. You don't need the flash bag for your error since you've defined it in your constraint. Are your errors bubbling? Again, I'll ask do you see the exception in your profiler??
  • Robert Wade
    Robert Wade about 6 years
    I made an edit to your controller (in my answer above). You had your return statement which redirected to the invite_show route outside of your isValid method. Therefore it would go to invite_show wether it was valid or not. You only want to go to that if it is valid, otherwise you stay with new.html.twig and are shown the exception. Also get rid of that pre submit event handler if you haven't already.
  • Admin
    Admin about 6 years
    Thank you it works however you can display it elsewhere than below the email input? like a flashbag.
  • Robert Wade
    Robert Wade about 6 years
    Yes you can specify where to point the error in the annotation or you can set error bubbling in your form so that the exception bubbles. If you do that make sure you have ((form_errors(form)}} in your template. Read up on validation constraints and forms in the Symfony cookbook.