使用Symfony2 / Symfony3中的FOSUserBundle删除/替换用户名字段

时间:2022-03-29 19:47:41

I only want to have email as mode of login, I don't want to have username. Is it possible with symfony2/symfony3 and FOSUserbundle?

我只想将电子邮件作为登录模式,我不想拥有用户名。是否可以使用symfony2 / symfony3和FOSUserbundle?

I read here http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

我在这里阅读http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

But then I am stuck with two constraint violations.

但后来我遇到了两个违反约束的问题。

Problem is if the user leaves the email address blank, I get two constraint violations:

问题是如果用户将电子邮件地址留空,我会遇到两个约束违规:

  • Please enter a username
  • 请填入一个用户名
  • Please enter an email
  • 请输入电子邮件

Is there a way to disable validation for a given field, or a better way to remove a field from the form altogether?

有没有办法禁用给定字段的验证,或者更好的方法从表单中删除字段?

7 个解决方案

#1


94  

A complete overview of what needs to be done

Here is a complete overview of what needs to be done. I have listed the different sources found here and there at the end of this post.

以下是需要完成的工作的完整概述。我在本文末尾列出了这里和那里发现的不同来源。

1. Override setter in Acme\UserBundle\Entity\User

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

    return $this;
}

2. Remove the username field from your form type

(in both RegistrationFormType and ProfileFormType)

(在RegistrationFormType和ProfileFormType中)

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

3. Validation constraints

As shown by @nurikabe, we have to get rid of the validation constraints provided by FOSUserBundle and create our own. This means that we will have to recreate all the constraints that were previously created in FOSUserBundle and remove the ones that concern the username field. The new validation groups that we will be creating are AcmeRegistration and AcmeProfile. We are therefore completely overriding the ones provided by the FOSUserBundle.

如@nurikabe所示,我们必须摆脱FOSUserBundle提供的验证约束并创建我们自己的。这意味着我们必须重新创建先前在FOSUserBundle中创建的所有约束,并删除与用户名字段有关的约束。我们将要创建的新验证组是AcmeRegistration和AcmeProfile。因此,我们完全凌驾于FOSU​​serBundle提供的那些上面。

3.a. Update config file in 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. Create Validation file Acme\UserBundle\Resources\config\validation.yml

That's the long bit:

这是长期的:

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. End

That's it! You should be good to go!

而已!你应该好好去!


Documents used for this post:

用于此帖子的文件:

#2


6  

I was able to do this by overriding both the registration and profile form type detailed here and removing the username field

我能够通过覆盖此处详述的注册和配置文件表单类型以及删除用户名字段来完成此操作

$builder->remove('username');

Along with overriding the setEmail method in my concrete user class:

在我的具体用户类中覆盖setEmail方法:

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

#3


2  

As Michael points out, this can be solved with a custom validation group. For example:

正如Michael所指出的,这可以通过自定义验证组来解决。例如:

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

Then in your entity (as defined by user_class: App\UserBundle\Entity\User) you can use the AppRegistration group:

然后在您的实体(由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;
    ...

This is what I ended up doing after posting that reply to the Symfony2 thread.

这是我在将回复发布到Symfony2线程后最终做的事情。

See http://symfony.com/doc/2.0/book/validation.html#validation-groups for full details.

有关完整详细信息,请参阅http://symfony.com/doc/2.0/book/validation.html#validation-groups。

#4


2  

As of Sf 2.3, a quick workaround is to set the username to any string in the _construct of your class User that extends BaseUser.

从Sf 2.3开始,一个快速的解决方法是将用户名设置为扩展BaseUser的类User的_construct中的任何字符串。

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

This way, the validator wont trigger any violation. But don't forget to set the email to the username as posted by Patt.

这样,验证器不会触发任何违规。但是不要忘记将电子邮件设置为Patt发布的用户名。

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

You may have to check other files for references to User:username and change accordingly.

您可能必须检查其他文件以获取对User:username的引用并相应地更改。

#5


1  

Have you tried customizing the validation?

您是否尝试过自定义验证?

To do this, you need to have your own bundle inheriting from the UserBundle, and then copy/adjust Resources/config/validation.xml. Plus, you need to set the validation_groups in the config.yml to your custom validation.

为此,您需要从UserBundle继承自己的包,然后复制/调整Resources / config / validation.xml。另外,您需要将config.yml中的validation_groups设置为自定义验证。

#6


1  

Instead of Validation replacing I prefer to replace RegistrationFormHandler#process, more precisely add new method processExtended(for example), which is a copy of original method, and use ut in RegistrationController. (Overriding: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps)

而不是Validation替换我更喜欢替换RegistrationFormHandler #process,更准确地添加新方法processExtended(例如),这是原始方法的副本,并在RegistrationController中使用ut。 (覆盖:https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps)

Before i bind register form i set username for example 'empty':

在我绑定注册表单之前,我设置了用户名,例如'empty':

class RegistrationFormHandler extends BaseHandler
{

    public function processExtended($confirmation = false)
    {
        $user = $this->userManager->createUser();
        $user->setUsername('empty'); //That's 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
}

Why? I prefer to user FOSUserBundle validation rules. Cuz if i replace Validation Group in config.yml for registration form i need to repeat validation rules for User in my own user entity.

为什么?我更喜欢使用FOSUserBundle验证规则。如果我将config.yml中的验证组替换为注册表单,我需要在我自己的用户实体中重复用户的验证规则。

#7


1  

If none of them works, a quick and dirty solution would be

如果它们都不起作用,那么快速而肮脏的解决方案就是

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

    return $this;
}

#1


94  

A complete overview of what needs to be done

Here is a complete overview of what needs to be done. I have listed the different sources found here and there at the end of this post.

以下是需要完成的工作的完整概述。我在本文末尾列出了这里和那里发现的不同来源。

1. Override setter in Acme\UserBundle\Entity\User

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

    return $this;
}

2. Remove the username field from your form type

(in both RegistrationFormType and ProfileFormType)

(在RegistrationFormType和ProfileFormType中)

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

3. Validation constraints

As shown by @nurikabe, we have to get rid of the validation constraints provided by FOSUserBundle and create our own. This means that we will have to recreate all the constraints that were previously created in FOSUserBundle and remove the ones that concern the username field. The new validation groups that we will be creating are AcmeRegistration and AcmeProfile. We are therefore completely overriding the ones provided by the FOSUserBundle.

如@nurikabe所示,我们必须摆脱FOSUserBundle提供的验证约束并创建我们自己的。这意味着我们必须重新创建先前在FOSUserBundle中创建的所有约束,并删除与用户名字段有关的约束。我们将要创建的新验证组是AcmeRegistration和AcmeProfile。因此,我们完全凌驾于FOSU​​serBundle提供的那些上面。

3.a. Update config file in 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. Create Validation file Acme\UserBundle\Resources\config\validation.yml

That's the long bit:

这是长期的:

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. End

That's it! You should be good to go!

而已!你应该好好去!


Documents used for this post:

用于此帖子的文件:

#2


6  

I was able to do this by overriding both the registration and profile form type detailed here and removing the username field

我能够通过覆盖此处详述的注册和配置文件表单类型以及删除用户名字段来完成此操作

$builder->remove('username');

Along with overriding the setEmail method in my concrete user class:

在我的具体用户类中覆盖setEmail方法:

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

#3


2  

As Michael points out, this can be solved with a custom validation group. For example:

正如Michael所指出的,这可以通过自定义验证组来解决。例如:

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

Then in your entity (as defined by user_class: App\UserBundle\Entity\User) you can use the AppRegistration group:

然后在您的实体(由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;
    ...

This is what I ended up doing after posting that reply to the Symfony2 thread.

这是我在将回复发布到Symfony2线程后最终做的事情。

See http://symfony.com/doc/2.0/book/validation.html#validation-groups for full details.

有关完整详细信息,请参阅http://symfony.com/doc/2.0/book/validation.html#validation-groups。

#4


2  

As of Sf 2.3, a quick workaround is to set the username to any string in the _construct of your class User that extends BaseUser.

从Sf 2.3开始,一个快速的解决方法是将用户名设置为扩展BaseUser的类User的_construct中的任何字符串。

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

This way, the validator wont trigger any violation. But don't forget to set the email to the username as posted by Patt.

这样,验证器不会触发任何违规。但是不要忘记将电子邮件设置为Patt发布的用户名。

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

You may have to check other files for references to User:username and change accordingly.

您可能必须检查其他文件以获取对User:username的引用并相应地更改。

#5


1  

Have you tried customizing the validation?

您是否尝试过自定义验证?

To do this, you need to have your own bundle inheriting from the UserBundle, and then copy/adjust Resources/config/validation.xml. Plus, you need to set the validation_groups in the config.yml to your custom validation.

为此,您需要从UserBundle继承自己的包,然后复制/调整Resources / config / validation.xml。另外,您需要将config.yml中的validation_groups设置为自定义验证。

#6


1  

Instead of Validation replacing I prefer to replace RegistrationFormHandler#process, more precisely add new method processExtended(for example), which is a copy of original method, and use ut in RegistrationController. (Overriding: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps)

而不是Validation替换我更喜欢替换RegistrationFormHandler #process,更准确地添加新方法processExtended(例如),这是原始方法的副本,并在RegistrationController中使用ut。 (覆盖:https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps)

Before i bind register form i set username for example 'empty':

在我绑定注册表单之前,我设置了用户名,例如'empty':

class RegistrationFormHandler extends BaseHandler
{

    public function processExtended($confirmation = false)
    {
        $user = $this->userManager->createUser();
        $user->setUsername('empty'); //That's 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
}

Why? I prefer to user FOSUserBundle validation rules. Cuz if i replace Validation Group in config.yml for registration form i need to repeat validation rules for User in my own user entity.

为什么?我更喜欢使用FOSUserBundle验证规则。如果我将config.yml中的验证组替换为注册表单,我需要在我自己的用户实体中重复用户的验证规则。

#7


1  

If none of them works, a quick and dirty solution would be

如果它们都不起作用,那么快速而肮脏的解决方案就是

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

    return $this;
}