I'm stuck with creating a user registration form with Symfony2.
I'm trying to define an Unique constraint on the email attribute of my User class.
Acme\APPBundle\Entity\User.php
namespace Acme\APPBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ORM\Entity
* @ORM\Entity(repositoryClass="Acme\APPBundle\Entity\UserRepository")
* @ORM\Table("users")
* @UniqueEntity(
* fields={"email"},
* message="email already used"
* )
*/
class User implements UserInterface, \Serializable
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=255, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
protected $email;
[...]
}
Acme\APPBundle\Form\Type\UserType.php
namespace Acme\APPBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('email', 'email');
$builder->add('password', 'repeated', array(
'first_name' => 'password',
'second_name' => 'confirm',
'type' => 'password',
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\APPBundle\Entity\User',
'cascade_validation' => true,
));
}
public function getName()
{
return 'user';
}
}
I've added the constraint following the documentation but I still get an exception like :
An exception occured while executing 'INSERT INTO users ( ... )'
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
It looks like my message value defined in annotations is ignored and the form validation is bypassed since it should fail before attempting to insert row in database.
Can you tell me what am I doing wrong ?
EDIT :
Following Matteo 'Ingannatore' G.'s advice I've noticed that my form is not properly validated. I forgot to mention that I use a registration class that extends the user form. I've written my code after what is explained in the Symfony Cookbook.
Thus I have :
Acme\APPBundle\Form\Model\Registration.php
namespace Acme\APPBundle\Form\Model;
use Symfony\Component\Validator\Constraints as Assert;
use Acme\APPBundle\Entity\User;
class Registration
{
/**
* @Assert\Type(type="Acme\APPBundle\Entity\User")
*/
protected $user;
/**
* @Assert\NotBlank()
* @Assert\True()
*/
protected $termsAccepted;
public function setUser(User $user)
{
$this->user = $user;
}
public function getUser()
{
return $this->user;
}
public function getTermsAccepted()
{
return $this->termsAccepted;
}
public function setTermsAccepted($termsAccepted)
{
$this->termsAccepted = (Boolean) $termsAccepted;
}
}
Acme\APPBundle\Form\Type\RegistrationType.php
namespace Acme\APPBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('user', new UserType());
$builder->add('terms', 'checkbox', array('property_path' => 'termsAccepted'));
}
public function getName()
{
return 'registration';
}
}
Acme\APPBundle\Controller\AccountController.php
namespace Acme\APPBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Acme\AccountBundle\Form\Type\RegistrationType;
use Acme\AccountBundle\Form\Model\Registration;
class AccountController extends Controller
{
public function registerAction()
{
$form = $this->createForm(new RegistrationType(), new Registration());
return $this->render('AcmeAPPBundle:Account:register.html.twig', array('form' => $form->createView()));
}
public function createAction()
{
$em = $this->getDoctrine()->getEntityManager();
$form = $this->createForm(new RegistrationType(), new Registration());
$form->handleRequest($this->getRequest());
if ($form->isValid()) { // FIXME !!
$registration = $form->getData();
$em->persist($registration->getUser());
$em->flush();
return $this->redirect($this->generateUrl('home'));
}
return $this->render('AcmeAPPBundle:Account:register.html.twig', array('form' => $form->createView()));
}
}
I guess the error I get might be caused by the fact that the Registration Form is validated, but the User Form within isn't submitted to validation. Am I wrong ?
How can I simply change that behaviour ? I saw there is a cascade_validation option but it seems to be useless here.
I think it's strange that Symfony Cookbook provides both guides to create a user provider and create a registration form but does not explain how to get those work along.