Вход в систему FOSUserBundle по электронной почте (Symfony2)

У меня есть вопрос о FOSUserBundle для Symfony 2.0.x. В документации вы можете найти способ изменить логин для работы с именем пользователя и электронной почтой. Это отлично работает! Но я хочу войти, чтобы работать только с электронной почтой. Таким образом, я добавил функцию в свой CustomUserManager (простирается от оригинала), который гарантирует, что вы просто сможете войти в систему с вашей электронной почтой.

namespace Frontend\UserBundle\Model;

use FOS\UserBundle\Entity\UserManager;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;

class CustomUserManager extends UserManager
{
    public function loadUserByUsername($email)
    {
        /*$user = $this->findUserByUsernameOrEmail($username);

        if (!$user) {
            throw new UsernameNotFoundException(sprintf('No user with name "%s" was found.', $username));
        }

        return $user;*/

        //Change it to only email (Default calls loadUserByUsername -> we send it to our own loadUserByEmail)
        return $this->loadUserByEmail($email);
    }

    public function loadUserByEmail($email)
    {
        $user = $this->findUserByEmail($email);

        if (!$user) {
            throw new UsernameNotFoundException(sprintf('No user with email "%s" was found.', $email));
        }

        return $user;

    }
}

Но теперь у меня есть проблема с тем, что мне нужно контролировать значения, которые сохраняются в сеансе. Он сохраняет мое имя пользователя в сеансе, и когда система проверяет это, не будет электронной почты (потому что он проверяет только электронную почту).

Итак, мой вопрос в том, как/где вы можете изменить значение, которое хранится внутри переменной имени пользователя.

Спасибо!

Ответы

Ответ 1

Это можно сделать, переопределив сеттеры в объекте User:

<?php

namespace Acme\UserBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ORM\Entity(repositoryClass="Acme\UserBundle\Entity\UserRepository")
 * @ORM\Table(name="users")
 */
class User extends BaseUser
{

    // ...

    // override methods for username and tie them with email field

    /**
     * Sets the email.
     *
     * @param string $email
     * @return User
     */
    public function setEmail($email)
    {
        $this->setUsername($email);

        return parent::setEmail($email);
    }

    /**
     * Set the canonical email.
     *
     * @param string $emailCanonical
     * @return User
     */
    public function setEmailCanonical($emailCanonical)
    {
        $this->setUsernameCanonical($emailCanonical);

        return parent::setEmailCanonical($emailCanonical);
    }

    // ...

}

Это не ясно из вашего вопроса, но из ваших пространств имен я предполагаю, что у вас есть собственный пакет, который использует FOSUserBundle в качестве родительского пакета (согласно документации FOSUserBundle, пример "b" ).

Если вы это сделаете, вы можете легко переопределить формы и шаблоны, чтобы удалить все поля username из пользовательского интерфейса и заменить их полями email. Поскольку вы переопределили настройки электронной почты, как указано выше, свойство username будет заполнено должным образом.

Хотя это работает, это не очень приятное решение. Недостатком является то, что в базе данных все равно будут столбцы username и usernameCanonical. Первоначально мы хотели полностью удалить их, но это потребовало бы слишком большого количества изменений в FOSUserBundle (атрибут имени пользователя требуется \FOS\UserBundle\Model\UserInterface, а код пакета зависит от него).

Ответ 2

Я нашел очень простое решение, возможно, не самое лучшее, но простота - сила!;)

Я пишу здесь на всякий случай, если это хорошо для всех.

Я помещаю логин/адрес электронной почты в поставщиков:

В app/conf/security.yml:

providers:
    fos_userbundle:
        id: fos_user.user_provider.username_email

А затем в представлении вашей формы входа я разрешаю только для входа с типом ввода = "email":

<input type="email" class="form-control" id="username" placeholder="E-Mail" name="_username" required="required"/>