Чат Telegram
Группа ВКонтакте
Регистрация на Symfony. Создание сущности пользователя

Регистрация на Symfony. Создание сущности пользователя

Вторую часть курса мы начнем с общей детали тысячи приложений - авторизации. У нас будет все: регистрация, вход-выход, кнопка "Запомнить меня" и отправка писем подтверждения регистрации на почту!

Чтобы реализовать регистрацию встроенными инструментами фреймворка, для начала нам нужно создать сущность User и имплементировать UserInterface, который даст нам стандартные методы вроде getRoles(), getUsername(), getSalt() и другие. Итак, через консоль или руками создайте сущность User, имплементируйте интерфейс UserInterface и добавьте методы, которые он требует. Вот как должен выглядеть ваш код на данном этапе:

Теперь давайте добавим поля для сущности. В первую очередь нам нужен id. Также добавим email, password, roles и plainPassword. PlainPassword не сохраняется в базе, он нужен для временного сохранения пароля из формы и валидации. Поле roles будет обычным json, в котором мы будем хранить роли, которыми владеет пользователь. Id у нас будет таким же, как и у сущности Post:

   /**
     * @var int
     *
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

Я думаю, не стоит объяснять эти аннотации, они достаточно красноречивы и без того. Давайте создадим остальные поля:

    /**
     * @var string
     *
     * @ORM\Column(type="string", unique=true)
     * @Assert\NotBlank()
     * @Assert\Email()
     */
    private $email;

    /**
     * @var string
     *
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @var string
     *
     * @Assert\NotBlank()
     */
    private $plainPassword;

    /**
     * @var array
     *
     * @ORM\Column(type="json_array")
     */
    private $roles = [];

Аннотация @Assert для вас новая, она предоставляет базовую валидацию: NotBlank() - поле не может быть пустым, Email() - введенные данные должны быть электронным адресом, то есть содержать @ и точку (как минимум). Также поле email у нас будет уникальным, что мы определили, указав unique=true. Над полем plainPassword нет аннотации Orm\Column(), потому что нам не надо сохранять это боле в базе, оно нужно только при регистрации пользователя.

Теперь давайте реализуем методы, которые нам дал UserInterface. Метод getRoles() пока будет возвращать обычный массив:

   /**
     * @return array
     */
    public function getRoles()
    {
        return [
            'ROLE_USER'
        ];
    }

Это значит, что любой пользователь, по умолчанию, будет обладать ролью User, что логично. Метод getPassword, собственно, будет обычным геттером пароля:

   /**
     * @return string
     */
    public function getPassword(): string
    {
        return $this->password;
    }

Соль нам не нужна, поэтому возвращаем null или можете вообще оставить метод пустым:

   /**
     * @return null
     */
    public function getSalt()
    {
        return null;
    }

А вот getUsername() может возвращать не только username (который я специально не добавил, чтобы показать особенность этого метода), он возвращает то, что для вас является достаточным правом для аутентификация на сайте - в нашем случае это email.

   /**
     * @return string
     */
    public function getUsername(): string
    {
        return $this->email;
    }

Метод eraseCredentials удаляет конфиденциальную информацию о пользователе, например, простой текстовый пароль, которым у нас является plainPassword:

    public function eraseCredentials()
    {
        $this->plainPassword = null;
    }

Не забудьте добавить геттеры и сеттеры для всех полей. В конечном итоге так будет выглядеть наша сущность:

<?php

declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\Table(name="user")
 * @UniqueEntity(fields={"email"}, message="У вас уже есть аккаунт")
 */
class User implements UserInterface
{
    /**
     * @var int
     *
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(type="string", unique=true)
     * @Assert\NotBlank()
     * @Assert\Email()
     */
    private $email;

    /**
     * @var string
     *
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @var string
     *
     * @Assert\NotBlank()
     */
    private $plainPassword;

    /**
     * @var array
     *
     * @ORM\Column(type="json_array")
     */
    private $roles = [];

    /**
     * @return array
     */
    public function getRoles()
    {
        return [
            'ROLE_USER'
        ];
    }

    /**
     * @param $roles
     *
     * @return $this
     */
    public function setRoles($roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @return string
     */
    public function getPassword(): string
    {
        return $this->password;
    }

    /**
     * @param string $password
     *
     * @return User
     */
    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @return null
     */
    public function getSalt()
    {
        return null;
    }

    /**
     * @return string
     */
    public function getUsername(): string
    {
        return $this->email;
    }

    public function eraseCredentials()
    {
        $this->plainPassword = null;
    }

    /**
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @param string $email
     *
     * @return $this
     */
    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @return string
     */
    public function getPlainPassword()
    {
        return $this->plainPassword;
    }

    /**
     * @param string $plainPassword
     *
     * @return User
     */
    public function setPlainPassword(string $plainPassword): self
    {
        $this->plainPassword = $plainPassword;

        return $this;
    }
}

В сеттерах вы могли заметить return $this, то есть сеттер устанавливает значение и возвращает текущий объект. Это позволит нам выполнять цепочку методов без прерывания:

$user
   ->setEmail('youremail@gmail.com')
   ->setPassword($password);

Для больших сущностей это крайне удобно, также это удобно, когда вы загружаете фикстуры в базу, где валидация не требуется и поэтому можно непрерывно добавлять (set) данные.

Вверху сущности вы могли заметить следующую аннотацию:

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\Table(name="user")
 * @UniqueEntity(fields={"email"}, message="У вас уже есть аккаунт")
 */

С первой вы уже знакомы: мы указываем, какой репозиторий отвечает за работу с этой сущностью. Если вы создавали сущности через команды, то у вас уже есть репозиторий:

php bin/console make:entity User

Если же нет, создайте его сами по примеру репозитория PostRepository.
Вторая аннотация показывает, как будет называться таблица в базе. Третья аннотация нужна для валидации конкретного поля сущности: в нашем случае это поле email. Также вы можете написать сообщение (message), которое покажется над полем email при регистрации, если пользователь уже существует.

Когда мы все сделали, нам нужно обновить наши миграции следующими командами:

php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate

Если вы все сделали правильно, в базе у вас появится таблица user. На этом мы закончили первую часть большой темы по созданию регистрации. До новых встреч!

loader
Логические задачи с собеседований