|
6 | 6 | How to Implement a Registration Form
|
7 | 7 | ====================================
|
8 | 8 |
|
9 |
| -The basics of creating a registration form are the same as any normal form. After |
10 |
| -all, you are creating an object with it (a user). However, since this is related |
11 |
| -to security, there are some additional aspects. This article explains it all. |
12 |
| - |
13 |
| -Before you get Started |
14 |
| ----------------------- |
15 |
| - |
16 |
| -To create the registration form, make sure you have these 3 things ready: |
17 |
| - |
18 |
| -**1) Install MakerBundle** |
19 |
| - |
20 |
| -Make sure MakerBundle is installed: |
21 |
| - |
22 |
| -.. code-block:: terminal |
23 |
| -
|
24 |
| - $ composer require --dev symfony/maker-bundle |
25 |
| -
|
26 |
| -If you need any other dependencies, MakerBundle will tell you when you run each |
27 |
| -command. |
28 |
| - |
29 |
| -**2) Create a User Class** |
30 |
| - |
31 |
| -If you already have a :ref:`User class <create-user-class>`, great! If not, you |
32 |
| - can generate one by running: |
33 |
| - |
34 |
| -.. code-block:: terminal |
35 |
| -
|
36 |
| - $ php bin/console make:user |
37 |
| -
|
38 |
| -For more info, see :ref:`create-user-class`. |
39 |
| - |
40 |
| -**3) (Optional) Create a Guard Authenticator** |
41 |
| - |
42 |
| -If you want to automatically authenticate your user after registration, create |
43 |
| -a Guard authenticator before generating your registration form. For details, see |
44 |
| -the :ref:`firewalls-authentication` section on the main security page. |
45 |
| - |
46 |
| -Adding the Registration System |
47 |
| ------------------------------- |
48 |
| - |
49 |
| -To easiest way to build your registration form is by using the ``make:registration-form`` |
50 |
| -command: |
51 |
| - |
52 |
| -.. versionadded:: 1.11 |
53 |
| - |
54 |
| - The ``make:registration-form`` was introduced in MakerBundle 1.11.0. |
55 |
| - |
56 |
| -.. code-block:: terminal |
57 |
| -
|
58 |
| - $ php bin/console make:registration-form |
59 |
| -
|
60 |
| -This command needs to know several things - like your ``User`` class and information |
61 |
| -about the properties on that class. The questions will vary based on your setup, |
62 |
| -because the command will guess as much as possible. |
63 |
| - |
64 |
| -When the command is done, congratulations! You have a functional registration form |
65 |
| -system that's ready for you to customize. The generated files will look something |
66 |
| -like what you see below. |
67 |
| - |
68 |
| -RegistrationFormType |
69 |
| -~~~~~~~~~~~~~~~~~~~~ |
70 |
| - |
71 |
| -The form class for the registration form will look something like this:: |
72 |
| - |
73 |
| - namespace App\Form; |
74 |
| - |
75 |
| - use App\Entity\User; |
76 |
| - use Symfony\Component\Form\AbstractType; |
77 |
| - use Symfony\Component\Form\Extension\Core\Type\PasswordType; |
78 |
| - use Symfony\Component\Form\FormBuilderInterface; |
79 |
| - use Symfony\Component\OptionsResolver\OptionsResolver; |
80 |
| - use Symfony\Component\Validator\Constraints\Length; |
81 |
| - use Symfony\Component\Validator\Constraints\NotBlank; |
82 |
| - |
83 |
| - class RegistrationFormType extends AbstractType |
84 |
| - { |
85 |
| - public function buildForm(FormBuilderInterface $builder, array $options) |
86 |
| - { |
87 |
| - $builder |
88 |
| - ->add('email') |
89 |
| - ->add('plainPassword', PasswordType::class, [ |
90 |
| - // instead of being set onto the object directly, |
91 |
| - // this is read and encoded in the controller |
92 |
| - 'mapped' => false, |
93 |
| - 'constraints' => [ |
94 |
| - new NotBlank([ |
95 |
| - 'message' => 'Please enter a password', |
96 |
| - ]), |
97 |
| - new Length([ |
98 |
| - 'min' => 6, |
99 |
| - 'minMessage' => 'Your password should be at least {{ limit }} characters', |
100 |
| - 'max' => 4096, |
101 |
| - ]), |
102 |
| - ], |
103 |
| - ]) |
104 |
| - ; |
105 |
| - } |
106 |
| - |
107 |
| - public function configureOptions(OptionsResolver $resolver) |
108 |
| - { |
109 |
| - $resolver->setDefaults([ |
110 |
| - 'data_class' => User::class, |
111 |
| - ]); |
112 |
| - } |
113 |
| - } |
114 |
| - |
115 |
| -.. _registration-password-max: |
116 |
| - |
117 |
| -.. sidebar:: Why the 4096 Password Limit? |
118 |
| - |
119 |
| - Notice that the ``plainPassword`` field has a max length of 4096 characters. |
120 |
| - For security purposes (`CVE-2013-5750`_), Symfony limits the plain password |
121 |
| - length to 4096 characters when encoding it. Adding this constraint makes |
122 |
| - sure that your form will give a validation error if anyone tries a super-long |
123 |
| - password. |
124 |
| - |
125 |
| - You'll need to add this constraint anywhere in your application where |
126 |
| - your user submits a plaintext password (e.g. change password form). The |
127 |
| - only place where you don't need to worry about this is your login form, |
128 |
| - since Symfony's Security component handles this for you. |
129 |
| - |
130 |
| -RegistrationController |
131 |
| -~~~~~~~~~~~~~~~~~~~~~~ |
132 |
| - |
133 |
| -The controller builds the form and, on submit, encodes the plain password and |
134 |
| -saves the user:: |
135 |
| - |
136 |
| - namespace App\Controller; |
137 |
| - |
138 |
| - use App\Entity\User; |
139 |
| - use App\Form\RegistrationFormType; |
140 |
| - use App\Security\StubAuthenticator; |
141 |
| - use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
142 |
| - use Symfony\Component\HttpFoundation\Request; |
143 |
| - use Symfony\Component\HttpFoundation\Response; |
144 |
| - use Symfony\Component\Routing\Annotation\Route; |
145 |
| - use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; |
146 |
| - use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; |
147 |
| - |
148 |
| - class RegistrationController extends AbstractController |
149 |
| - { |
150 |
| - /** |
151 |
| - * @Route("/register", name="app_register") |
152 |
| - */ |
153 |
| - public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder): Response |
154 |
| - { |
155 |
| - $user = new User(); |
156 |
| - $form = $this->createForm(RegistrationFormType::class, $user); |
157 |
| - $form->handleRequest($request); |
158 |
| - |
159 |
| - if ($form->isSubmitted() && $form->isValid()) { |
160 |
| - // encode the plain password |
161 |
| - $user->setPassword( |
162 |
| - $passwordEncoder->encodePassword( |
163 |
| - $user, |
164 |
| - $form->get('plainPassword')->getData() |
165 |
| - ) |
166 |
| - ); |
167 |
| - |
168 |
| - $entityManager = $this->getDoctrine()->getManager(); |
169 |
| - $entityManager->persist($user); |
170 |
| - $entityManager->flush(); |
171 |
| - |
172 |
| - // do anything else you need here, like send an email |
173 |
| - |
174 |
| - return $this->redirectToRoute('app_homepage'); |
175 |
| - } |
176 |
| - |
177 |
| - return $this->render('registration/register.html.twig', [ |
178 |
| - 'registrationForm' => $form->createView(), |
179 |
| - ]); |
180 |
| - } |
181 |
| - } |
182 |
| - |
183 |
| -register.html.twig |
184 |
| -~~~~~~~~~~~~~~~~~~ |
185 |
| - |
186 |
| -The template renders the form: |
187 |
| - |
188 |
| -.. code-block:: html+twig |
189 |
| - |
190 |
| - {% extends 'base.html.twig' %} |
191 |
| - |
192 |
| - {% block title %}Register{% endblock %} |
193 |
| - |
194 |
| - {% block body %} |
195 |
| - <h1>Register</h1> |
196 |
| - |
197 |
| - {{ form_start(registrationForm) }} |
198 |
| - {{ form_row(registrationForm.email) }} |
199 |
| - {{ form_row(registrationForm.plainPassword) }} |
200 |
| - |
201 |
| - <button class="btn">Register</button> |
202 |
| - {{ form_end(registrationForm) }} |
203 |
| - {% endblock %} |
204 |
| - |
205 |
| -Adding a "accept terms" Checkbox |
206 |
| --------------------------------- |
207 |
| - |
208 |
| -Sometimes, you want a "Do you accept the terms and conditions" checkbox on your |
209 |
| -registration form. The only trick is that you want to add this field to your form |
210 |
| -without adding an unnecessary new ``termsAccepted`` property to your ``User`` entity |
211 |
| -that you'll never need. |
212 |
| - |
213 |
| -To do this, add a ``termsAccepted`` field to your form, but set its |
214 |
| -:ref:`mapped <reference-form-option-mapped>` option to ``false``:: |
215 |
| - |
216 |
| - // src/Form/UserType.php |
217 |
| - // ... |
218 |
| - use Symfony\Component\Form\Extension\Core\Type\CheckboxType; |
219 |
| - use Symfony\Component\Form\Extension\Core\Type\EmailType; |
220 |
| - use Symfony\Component\Validator\Constraints\IsTrue; |
221 |
| - |
222 |
| - class UserType extends AbstractType |
223 |
| - { |
224 |
| - public function buildForm(FormBuilderInterface $builder, array $options) |
225 |
| - { |
226 |
| - $builder |
227 |
| - ->add('email', EmailType::class) |
228 |
| - // ... |
229 |
| - ->add('termsAccepted', CheckboxType::class, [ |
230 |
| - 'mapped' => false, |
231 |
| - 'constraints' => new IsTrue(), |
232 |
| - ]) |
233 |
| - ; |
234 |
| - } |
235 |
| - } |
236 |
| - |
237 |
| -The :ref:`constraints <form-option-constraints>` option is also used, which allows |
238 |
| -us to add validation, even though there is no ``termsAccepted`` property on ``User``. |
239 |
| - |
240 |
| -Manually Authenticating after Success |
241 |
| -------------------------------------- |
242 |
| - |
243 |
| -If you're using Guard authentication, you can :ref:`automatically authenticate <guard-manual-auth>` |
244 |
| -after registration is successful. The generator may have already configured your |
245 |
| -controller to take advantage of this. |
246 |
| - |
247 |
| -.. _`CVE-2013-5750`: https://symfony.com/blog/cve-2013-5750-security-issue-in-fosuserbundle-login-form |
| 9 | +This article has been removed because it only explained things that are |
| 10 | +already explained in other articles. Specifically, to implement a registration |
| 11 | +form you must: |
| 12 | + |
| 13 | +#. :ref:`Define a class to represent users <create-user-class>`; |
| 14 | +#. :doc:`Create a form </forms>` to ask for the registration information; |
| 15 | +#. Create :doc:`a controller </controller>` to :ref:`process the form <processing-forms>`; |
| 16 | +#. :ref:`Protect some parts of your application <security-authorization>` so |
| 17 | + only registered users can access to them. |
0 commit comments