Как реализовать простую форму регистрации¶
Создать форму регистрации достаточно просто - это действительно значит просто
создать форму, которая будет обновлять некоторый объект модели User
(сущность
Doctrine в этом примере) и потом сохранять его.
Для начала, убедитесь, что у вас установлены все необходимые зависимости:
1 | $ composer require doctrine form security validator
|
Tip
Популярный FOSUserBundle предоставляет форму регистрации, форму сброса пароля и другой функционал управления пользователем.
Если у вас еще нет сущности User
и работающей системы входа, начните с
провайдера сущностей
.
Ваша сущность User
скорее всего будет иметь хотя бы одно из следущих полей:
username
- Будет использовано для выполнения входа, разве что вы вместо этого захотите, чтобы ваш пользователь выполнял вход через электронную почту (в таком случае, это поле не нужно).
email
- Хорошая информация для сбора. Вы также можете позволить пользователям выполнять вход через электронную почту.
password
- Зашифрованный пароль.
plainPassword
- Это поле не сохраняется: (заметьте, что над ним нет
@ORM\Column
). Оно временно сохраняет простой пароль из формы регистрации. Это поле может быть валидировано и потом использовано, для заполнения поляpassword
.
С добавлением некоторой валидации, вам класс может выглядеть как-то так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | // src/Entity/User.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Entity
* @UniqueEntity(fields="email", message="Email already taken")
* @UniqueEntity(fields="username", message="Username already taken")
*/
class User implements UserInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
private $email;
/**
* @ORM\Column(type="string", length=255, unique=true)
* @Assert\NotBlank()
*/
private $username;
/**
* @Assert\NotBlank()
* @Assert\Length(max=4096)
*/
private $plainPassword;
/**
* Нижеуказанная длина зависит от "алгоритма", который вы используете для шифрования
* пароля, но это также хорошо работает с bcrypt.
*
* @ORM\Column(type="string", length=64)
*/
private $password;
// другие свойства и методы
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
public function getSalt()
{
// Алгоритмы bcrypt и argon2i не требуют отдельной соли.
// Вам *может* понадобиться настоящая соль, если вы выберете другой кодировшик.
return null;
}
// другие методы, включая методы безопасности вроде getRoles()
}
|
Класс UserInterface
требует
несколько других методов и ваш файл security.yml
должен быть сконфигурирован
соответственно, чтобы работать с сущностью User
. Для более полного примера,
см. статью Провайдер сущностей.
Создание формы для сущности¶
Залее, создайте форму для сущности User
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // src/Form/UserType.php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class)
->add('username', TextType::class)
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
));
}
}
|
Существуют всего три поля: email
, username
и plainPassword
(повторяемое, чтобы подтвердить введенный пароль).
Tip
Чтобы изучить больше вещей о компонентне Формы, прочтите справочник Forms guide.
Управление отправкой форм¶
Далее вам понадобится контроллер, чтобы управлять отображением и оправкой формы. Если форма отправлена, контроллер выполняет валидацию и сохраняет данные в DB:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | // src/Controller/RegistrationController.php
namespace App\Controller;
use App\Form\UserType;
use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class RegistrationController extends Controller
{
/**
* @Route("/register", name="user_registration")
*/
public function registerAction(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
// 1) постройте форму
$user = new User();
$form = $this->createForm(UserType::class, $user);
// 2) обработайте отправку (произойдёт только в POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// 3) Зашифруйте пароль (вы также можете сделать это через слушатель Doctrine)
$password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
// 4) сохраните Пользователя!
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
// ... сделайте любую другую работу - вроде отправки письма и др
// может, установите "флеш" сообщение об успешном выполнении для пользователя
return $this->redirectToRoute('replace_with_some_route');
}
return $this->render(
'registration/register.html.twig',
array('form' => $form->createView())
);
}
}
|
Чтобы определить алгоритм, использованный для шифрования пароля в 3-ем шаге, сконфигурируйте кодировщик в конфигурации безопасности:
- YAML
1 2 3 4
# config/packages/security.yaml security: encoders: App\Entity\User: bcrypt
- XML
1 2 3 4 5 6 7 8 9 10 11
<!-- config/packages/security.xml --> <?xml version="1.0" charset="UTF-8" ?> <srv:container xmlns="http://symfony.com/schema/dic/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:srv="http://symfony.com/schema/dic/services" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <config> <encoder class="App\Entity\User">bcrypt</encoder> </config> </srv:container>
- PHP
1 2 3 4 5 6 7 8
// config/packages/security.php use App\Entity\User; $container->loadFromExtension('security', array( 'encoders' => array( User::class => 'bcrypt', ), ));
В этом случае, используется рекомендованный алгоритм bcrypt
. Если нужно,
просмотрите статью шифрование пользовательских паролей.
Далее, создайте шаблон:
1 2 3 4 5 6 7 8 9 10 | {# templates/registration/register.html.twig #}
{{ form_start(form) }}
{{ form_row(form.username) }}
{{ form_row(form.email) }}
{{ form_row(form.plainPassword.first) }}
{{ form_row(form.plainPassword.second) }}
<button type="submit">Register!</button>
{{ form_end(form) }}
|
См. How to Customize Form Rendering, чтобы узнать больше.
Обновление вашей схемы DB¶
Если во время этого туториала вы обновляли сущность User
, то вам нужно
обновить вашу схему DB, используя эту команду:
1 2 | $ php bin/console doctrine:migrations:diff
$ php bin/console doctrine:migrations:migrate
|
Вот и всё! Переходите к /register
, чтобы опробовать!
Форма регистрации только с электронной почты (без имени пользователя)¶
Если вы хотите, чтобы ваши пользователи выполняли вход через электронную почту, и
вам не нужно имя пользователя, то вы можете полностью удалить его из вашей сущности
User
. Вместо этого, заставьте getUsername()
возвращать свойство``email``:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // src/Entity/User.php
// ...
class User implements UserInterface
{
// ...
public function getUsername()
{
return $this->email;
}
// ...
}
|
Далее, просто обновите раздел``providers`` вашего файла security.yml
, чтобы
Symfony знала, как загружать ваших пользователей через свойство email
в качестве
логина. См. Аутентификация с пользовательским провайдером сущностей.
Добавление поля (чекбокса) "принятие условий"¶
Иногда вам может захотеться добавить поле "Принимаете ли вы условия" в вашу форму
регистрации. Фокус в том, что вы хотите добавить это поле к форме, не добавляя нового
ненужного свойства termsAccepted
к вашей сущности User
, так как оно вам никогда
не понадобится.
Чтобы сделать это, добавьте в вашу форму поле termsAccepted
, но установите его опцию
отображение как false
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // src/Form/UserType.php
// ...
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class);
// ...
->add('termsAccepted', CheckboxType::class, array(
'mapped' => false,
'constraints' => new IsTrue(),
))
);
}
}
|
Опция ограничений также может быть использована, что
позволяет нам добавлять валидацию, несмотря на то, что у User
нет свойства termsAccepted
.
Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.