|
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