Подтвердить что ты не робот

Удалите/замените поле имени пользователя по электронной почте с помощью FOSUserBundle в Symfony2/Symfony3

Я хочу, чтобы в качестве режима входа в систему использовалась электронная почта, а не имя пользователя. Это возможно с symfony2/symfony3 и FOSUserbundle?

Я читаю здесь http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

Но потом я застрял с двумя нарушениями ограничений.

Проблема в том, что если пользователь оставляет адрес электронной почты пустым, я получаю два нарушения ограничения:

  • Пожалуйста введите имя пользователя
  • Пожалуйста, введите адрес электронной почты

Есть ли способ отключить проверку для данного поля или лучший способ полностью удалить поле из формы?

4b9b3361

Ответ 1

Полный обзор того, что необходимо сделать

Вот полный обзор того, что необходимо сделать. Я перечислил различные источники, найденные здесь и там, в конце этого поста.

1. Переопределите установщик в Acme\UserBundle\Entity\User

public function setEmail($email)
{
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);

    return $this;
}

2. Удалите поле имени пользователя из вашего типа формы

(как в RegistrationFormType и в ProfileFormType)

public function buildForm(FormBuilder $builder, array $options)
{
    parent::buildForm($builder, $options);
    $builder->remove('username');  // we use email as the username
    //..
}

3. Ограничения валидации

Как показывает @nurikabe, мы должны избавиться от ограничений проверки, предоставляемых FOSUserBundle и создать наши собственные. Это означает, что нам придется воссоздать все ограничения, которые были ранее созданы в FOSUserBundle и удалить те, которые относятся к полю username. Мы AcmeRegistration новые группы проверки - AcmeRegistration и AcmeProfile. Поэтому мы полностью переопределяем те, которые предоставляются FOSUserBundle.

3.a. Обновите файл конфигурации в Acme\UserBundle\Resources\config\config.yml

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: Acme\UserBundle\Entity\User
    registration:
        form:
            type: acme_user_registration
            validation_groups: [AcmeRegistration]
    profile:
        form:
            type: acme_user_profile
            validation_groups: [AcmeProfile]

3.b. Создайте файл проверки Acme\UserBundle\Resources\config\validation.yml

Это долго

Acme\UserBundle\Entity\User:
    properties:
    # Your custom fields in your user entity, here is an example with FirstName
        firstName:
            - NotBlank:
                message: acme_user.first_name.blank
                groups: [ "AcmeProfile" ]
            - Length:
                min: 2
                minMessage: acme_user.first_name.short
                max: 255
                maxMessage: acme_user.first_name.long
                groups: [ "AcmeProfile" ]



# Note: We still want to validate the email
# See FOSUserBundle/Resources/config/validation/orm.xml to understand
# the UniqueEntity constraint that was originally applied to both
# username and email fields
#
# As you can see, we are only applying the UniqueEntity constraint to 
# the email field and not the username field.
FOS\UserBundle\Model\User:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: 
             fields: email
             errorPath: email 
             message: fos_user.email.already_used
             groups: [ "AcmeRegistration", "AcmeProfile" ]

    properties:
        email:
            - NotBlank:
                message: fos_user.email.blank
                groups: [ "AcmeRegistration", "AcmeProfile" ]
            - Length:
                min: 2
                minMessage: fos_user.email.short
                max: 255
                maxMessage: fos_user.email.long
                groups: [ "AcmeRegistration", "ResetPassword" ]
            - Email:
                message: fos_user.email.invalid
                groups: [ "AcmeRegistration", "AcmeProfile" ]
        plainPassword:
            - NotBlank:
                message: fos_user.password.blank
                groups: [ "AcmeRegistration", "ResetPassword", "ChangePassword" ]
            - Length:
                min: 2
                max: 4096
                minMessage: fos_user.password.short
                groups: [ "AcmeRegistration", "AcmeProfile", "ResetPassword", "ChangePassword"]

FOS\UserBundle\Model\Group:
    properties:
        name:
            - NotBlank:
                message: fos_user.group.blank
                groups: [ "AcmeRegistration" ]
            - Length:
                min: 2
                minMessage: fos_user.group.short
                max: 255
                maxMessage: fos_user.group.long
                groups: [ "AcmeRegistration" ]

FOS\UserBundle\Propel\User:
    properties:
        email:
            - NotBlank:
                message: fos_user.email.blank
                groups: [ "AcmeRegistration", "AcmeProfile" ]
            - Length:
                min: 2
                minMessage: fos_user.email.short
                max: 255
                maxMessage: fos_user.email.long
                groups: [ "AcmeRegistration", "ResetPassword" ]
            - Email:
                message: fos_user.email.invalid
                groups: [ "AcmeRegistration", "AcmeProfile" ]

        plainPassword:
            - NotBlank:
                message: fos_user.password.blank
                groups: [ "AcmeRegistration", "ResetPassword", "ChangePassword" ]
            - Length:
                min: 2
                max: 4096
                minMessage: fos_user.password.short
                groups: [ "AcmeRegistration", "AcmeProfile", "ResetPassword", "ChangePassword"]


FOS\UserBundle\Propel\Group:
    properties:
        name:
            - NotBlank:
                message: fos_user.group.blank
                groups: [ "AcmeRegistration" ]
            - Length:
                min: 2
                minMessage: fos_user.group.short
                max: 255
                maxMessage: fos_user.group.long
                groups: [ "AcmeRegistration" ]

4. Конец

Это! Вам должно быть хорошо идти!


Документы, использованные для этого поста:

Ответ 2

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

$builder->remove('username');

Наряду с переопределением метода setEmail в моем конкретном пользовательском классе:

 public function setEmail($email) 
 {
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);
  }

Ответ 3

Как указывает Майкл, это можно решить с помощью специальной группы проверки. Например:

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: App\UserBundle\Entity\User
    registration:
        form:
            type: app_user_registration
            validation_groups: [AppRegistration]

Затем в вашей сущности (как определено user_class: App\UserBundle\Entity\User) вы можете использовать группу AppRegistration:

class User extends BaseUser {

    /**
     * Override $email so that we can apply custom validation.
     * 
     * @Assert\NotBlank(groups={"AppRegistration"})
     * @Assert\MaxLength(limit="255", message="Please abbreviate.", groups={"AppRegistration"})
     * @Assert\Email(groups={"AppRegistration"})
     */
    protected $email;
    ...

Вот что я сделал после публикации ответа на поток Symfony2.

Подробнее см. http://symfony.com/doc/2.0/book/validation.html#validation-groups.

Ответ 4

Как и в случае Sf 2.3, быстрое обходное решение заключается в том, чтобы установить имя пользователя в любую строку в _construct вашего класса User, который расширяет BaseUser.

public function __construct()
    {
        parent::__construct();
        $this->username = 'username';
    }

Таким образом, валидатор не вызовет никаких нарушений. Но не забудьте указать адрес электронной почты для имени пользователя, отправленного Patt.

public function setEmail($email)
{
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);
}

Возможно, вам придется проверить другие файлы для ссылок на User: username и соответственно изменить.

Ответ 5

Вы пробовали настроить валидацию?

Для этого вам нужно иметь собственный набор, наследующий от UserBundle, а затем скопировать/настроить ресурсы /config/validation.xml. Кроме того, вам нужно установить validation_groups в config.yml для вашей пользовательской проверки.

Ответ 6

Вместо замены Validation я предпочитаю заменять процесс RegistrationFormHandler #, точнее добавить новый метод processExtended (например), который является копией исходного метода, и использовать ut в RegistrationController. (Переопределение: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps)

Прежде чем привязать регистрационную форму, я задаю имя пользователя, например, "empty":

class RegistrationFormHandler extends BaseHandler
{

    public function processExtended($confirmation = false)
    {
        $user = $this->userManager->createUser();
        $user->setUsername('empty'); //That it!!
        $this->form->setData($user);

        if ('POST' == $this->request->getMethod()) {


            $this->form->bindRequest($this->request);

            if ($this->form->isValid()) {

                $user->setUsername($user->getEmail()); //set email as username!!!!!
                $this->onSuccess($user, $confirmation);

                /* some my own logic*/

                $this->userManager->updateUser($user);
                return true;
            }
        }

        return false;
    }
    // replace other functions if you want
}

Почему? Я предпочитаю правила проверки FOSUserBundle пользователя. Если я заменил Validation Group в config.yml для регистрационной формы, мне нужно повторить правила проверки для Пользователя в моей собственной пользовательской сущности.

Ответ 7

Если ни одна из них не работает, быстрое и грязное решение будет

public function setEmail($email)
{
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername(uniqid()); // We do not care about the username

    return $this;
}

Ответ 8

Вы можете сделать имя пользователя обнуляемым, а затем удалить его из формы:

Сначала в AppBundle\Entity\User добавьте аннотацию над классом User.

use Doctrine\ORM\Mapping\AttributeOverrides;
use Doctrine\ORM\Mapping\AttributeOverride;

/**
 * User
 *
 * @ORM\Table(name="fos_user")
 *  @AttributeOverrides({
 *     @AttributeOverride(name="username",
 *         [email protected]\Column(
 *             name="username",
 *             type="string",
 *             length=255,
 *             unique=false,
 *             nullable=true
 *         )
 *     ),
 *     @AttributeOverride(name="usernameCanonical",
 *         [email protected]\Column(
 *             name="usernameCanonical",
 *             type="string",
 *             length=255,
 *             unique=false,
 *             nullable=true
 *         )
 *     )
 * })
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User extends BaseUser
{
//..

Когда вы запускаете php bin/console doctrine:schema:update --force это сделает имя пользователя обнуляемым в базе данных.

Во-вторых, в вашей форме введите AppBundle\Form\RegistrationType, удалите имя пользователя из формы.

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->remove('username');
        // you can add other fields with ->add('field_name')
    }

Теперь вы не увидите поле имени пользователя в форме (спасибо $builder->remove('username');). и когда вы отправляете форму, вы больше не получите ошибку проверки "Пожалуйста, введите имя пользователя", потому что она больше не требуется (благодаря аннотации).

Источник: https://github.com/FriendsOfSymfony/FOSUserBundle/issues/982#issuecomment-12931663

Ответ 9

Простое решение состоит в том, чтобы зайти в вашу базу данных и установить для имени пользователя и имени пользователя canical значение NULL и покончить с этим!