From a9ebfee7603e680549bf8d0d1a7f34d25f80b4b1 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Fri, 27 Jul 2012 09:53:22 +0100 Subject: [PATCH 1/3] Readded cookbook article which had been moved to MongoDBBundle documentation --- cookbook/doctrine/index.rst | 1 + cookbook/doctrine/registration_form.rst | 274 ++++++++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 cookbook/doctrine/registration_form.rst diff --git a/cookbook/doctrine/index.rst b/cookbook/doctrine/index.rst index 8a497457eb2..930a8262608 100644 --- a/cookbook/doctrine/index.rst +++ b/cookbook/doctrine/index.rst @@ -11,3 +11,4 @@ Doctrine reverse_engineering multiple_entity_managers custom_dql_functions + registration_form diff --git a/cookbook/doctrine/registration_form.rst b/cookbook/doctrine/registration_form.rst new file mode 100644 index 00000000000..19f6c2e2f68 --- /dev/null +++ b/cookbook/doctrine/registration_form.rst @@ -0,0 +1,274 @@ +.. index:: + single: Doctrine; Simple Registration Form + single: Form; Simple Registration Form + +How to implement a simple Registration Form +=========================================== + +Some forms have extra fields whose values don't need to be stored in the +database. For example, you may want to create a registration form with some +extra fields (like a "terms accepted" checkbox field) and embed the form +that actually stores the account information. + +The simple User model +--------------------- + +You have a simple ``User`` entity mapped to the database:: + + // src/Acme/AccountBundle/Document/User.php + namespace Acme\AccountBundle\Document; + + use Doctrine\ORM\Mapping as ORM; + use Symfony\Component\Validator\Constraints as Assert; + use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + + /** + * @ORM\Entity + * @UniqueEntity(fields="email", message="Email already taken") + */ + class User + { + /** + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @ORM\Column(type="string", length=255) + * @Assert\NotBlank() + * @Assert\Email() + */ + protected $email; + + /** + * @ORM\Column(type="string", length=255) + * @Assert\NotBlank() + */ + protected $password; + + public function getId() + { + return $this->id; + } + + public function getEmail() + { + return $this->email; + } + + public function setEmail($email) + { + $this->email = $email; + } + + public function getPassword() + { + return $this->password; + } + + // stupid simple encryption (please don't copy it!) + public function setPassword($password) + { + $this->password = sha1($password); + } + } + +This ``User`` document contains three fields and two of them (email and +password) should display on the form. The email property must be unique +in the database, this is enforced by adding this validation at the top of +the class. + +.. note:: + + If you want to integrate this User within the security system,you need + to implement the :ref:`UserInterface` of the + security component . + +Create a Form for the Model +--------------------------- + +Next, create the form for the ``User`` model:: + + // src/Acme/AccountBundle/Form/Type/UserType.php + namespace Acme\AccountBundle\Form\Type; + + use Symfony\Component\Form\AbstractType; + use Symfony\Component\Form\Extension\Core\Type\RepeatedType; + use Symfony\Component\Form\FormBuilder; + + class UserType extends AbstractType + { + public function buildForm(FormBuilder $builder, array $options) + { + $builder->add('email', 'email'); + $builder->add('password', 'repeated', array( + 'first_name' => 'password', + 'second_name' => 'confirm', + 'type' => 'password' + )); + } + + public function getDefaultOptions(array $options) + { + return array('data_class' => 'Acme\AccountBundle\Document\User'); + } + + public function getName() + { + return 'user'; + } + } + +There are just two fields: email and password (repeated to confirm the entered +password). The ``data_class`` option tells the form the name of data class +(i.e. your ``User`` document). + +.. tip:: + + To explore more things about the form component, read this documentation :doc:`file`. + +Embedding the User form into a Registration Form +------------------------------------------------ + +The form that you'll use for the registration page is not the same as the +form for used to simply modify the ``User`` (i.e. ``UserType``). The registration +form will contain further fields like "accept the terms", whose value is +won't be stored into database. + +In other words, create a second form for registration, which embeds the ``User`` +form and adds the extra field needed. Start by creating a simple class which +represents the "registration":: + + // src/Acme/AccountBundle/Form/Model/Registration.php + namespace Acme\AccountBundle\Form\Model; + + use Symfony\Component\Validator\Constraints as Assert; + + use Acme\AccountBundle\Document\User; + + class Registration + { + /** + * @Assert\Type(type="Acme\AccountBundle\Document\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; + } + } + +Next, create the form for this ``Registration`` model:: + + // src/Acme/AccountBundle/Form/Type/RegistrationType.php + namespace Acme\AccountBundle\Form\Type; + + use Symfony\Component\Form\AbstractType; + use Symfony\Component\Form\Extension\Core\Type\RepeatedType; + use Symfony\Component\Form\FormBuilder; + + class RegistrationType extends AbstractType + { + public function buildForm(FormBuilder $builder, array $options) + { + $builder->add('user', new UserType()); + $builder->add('terms', 'checkbox', array('property_path' => 'termsAccepted')); + } + + public function getName() + { + return 'registration'; + } + } + +You don't need to use special method for embedding the ``UserType`` form. +A form is a field, too - so you can add this like any other field, with the +expectation that the corresponding ``user`` property will hold an instance +of the class ``UserType``. + +Handling the Form Submission +---------------------------- + +Next, you need a controller to handle the form. Start by creating a simple +controller for displaying the registration form:: + + // src/Acme/AccountBundle/Controller/AccountController.php + namespace Acme\AccountBundle\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('AcmeAccountBundle:Account:register.html.twig', array('form' => $form->createView())); + } + } + +and its template: + +.. code-block:: html+jinja + + {# src/Acme/AccountBundle/Resources/views/Account/register.html.twig #} + +
+ {{ form_widget(form) }} + + +
+ +Finally, create the controller which handles the form submission. This performs +the validation and saves the data into the database:: + + public function createAction() + { + $em = $this->getDoctrine()->getEntityManager(); + + $form = $this->createForm(new RegistrationType(), new Registration()); + + $form->bindRequest($this->getRequest()); + + if ($form->isValid()) { + $registration = $form->getData(); + + $em->persist($registration->getUser()); + $em->flush(); + + return $this->redirect(...); + } + + return $this->render('AcmeAccountBundle:Account:register.html.twig', array('form' => $form->createView())); + } + +That's it! Your form now validates, and allows you to save the ``User`` +object to the database. From 8c2efee20e92efa6155c116a317accc54880d7b6 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Fri, 27 Jul 2012 11:04:43 +0100 Subject: [PATCH 2/3] Fixed CS issues --- cookbook/doctrine/registration_form.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cookbook/doctrine/registration_form.rst b/cookbook/doctrine/registration_form.rst index 19f6c2e2f68..041c5bce330 100644 --- a/cookbook/doctrine/registration_form.rst +++ b/cookbook/doctrine/registration_form.rst @@ -106,7 +106,7 @@ Next, create the form for the ``User`` model:: $builder->add('password', 'repeated', array( 'first_name' => 'password', 'second_name' => 'confirm', - 'type' => 'password' + 'type' => 'password', )); } @@ -178,7 +178,7 @@ represents the "registration":: public function setTermsAccepted($termsAccepted) { - $this->termsAccepted = (boolean)$termsAccepted; + $this->termsAccepted = (boolean) $termsAccepted; } } @@ -240,7 +240,6 @@ and its template: .. code-block:: html+jinja {# src/Acme/AccountBundle/Resources/views/Account/register.html.twig #} -
{{ form_widget(form) }} From 7daab996356ae16282970e5a1b0b6230769deee0 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Fri, 27 Jul 2012 16:09:11 +0100 Subject: [PATCH 3/3] CS fix --- cookbook/doctrine/registration_form.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/doctrine/registration_form.rst b/cookbook/doctrine/registration_form.rst index 041c5bce330..be35fa17281 100644 --- a/cookbook/doctrine/registration_form.rst +++ b/cookbook/doctrine/registration_form.rst @@ -178,7 +178,7 @@ represents the "registration":: public function setTermsAccepted($termsAccepted) { - $this->termsAccepted = (boolean) $termsAccepted; + $this->termsAccepted = (Boolean) $termsAccepted; } }