php 使用 Symfony2 / Symfony3 中的 FOSUserBundle 使用电子邮件删除/替换用户名字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8832916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 05:36:41  来源:igfitidea点击:

Remove / Replace the username field with email using FOSUserBundle in Symfony2 / Symfony3

phpsymfonyfosuserbundle

提问by Mirage

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?

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

回答by Mick

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

1. 覆盖 setter 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

2. 从您的表单类型中删除用户名字段

(in both RegistrationFormTypeand 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

3. 验证约束

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

正如@nurikabe 所示,我们必须摆脱由提供的验证约束FOSUserBundle并创建自己的验证约束。这意味着我们将不得不重新创建之前在其中创建的所有约束FOSUserBundle并删除与该username字段相关的约束。我们将创建的新验证组是AcmeRegistrationAcmeProfile。因此,我们完全覆盖了FOSUserBundle.

3.a. Update config file in Acme\UserBundle\Resources\config\config.yml

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

3.b. 创建验证文件 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

4. 结束

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

就是这样!你应该很高兴去!



Documents used for this post:

本帖使用的文件:

回答by Ben_hawk

I was able to do this by overriding both the registration and profile form type detailed hereand 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);
  }

回答by iambray

As of Sf 2.3, a quick workaroundis 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 的引用并进行相应更改。

回答by nurikabe

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

正如迈克尔指出的那样,这可以通过自定义验证组来解决。例如:

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-groupsfor full details.

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

回答by ZloyPotroh

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)

我更喜欢替换RegistrationFormHandler#process 而不是Validation 替换,更准确地说是添加新方法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':

在绑定注册表之前,我设置了用户名,例如“空”:

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 中的验证组替换为注册表单,我需要在我自己的用户实体中为用户重复验证规则。

回答by Michael Sauter

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 设置为您的自定义验证。

回答by getvivekv

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;
}

回答by Eissa

You can make the username nullable and then remove it from the form type:

您可以使用户名可以为空,然后将其从表单类型中删除:

First, in AppBundle\Entity\User, add the annotation above the User class

首先,在AppBundle\Entity\User 中,在 User 类上方添加注解

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

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

When you run php bin/console doctrine:schema:update --forceit will make the username nullable in the database.

当您运行时,php bin/console doctrine:schema:update --force它将使数据库中的用户名可以为空。

Second, in your form type AppBundle\Form\RegistrationType, remove the username from the form.

其次,在您的表单类型AppBundle\Form\RegistrationType 中,从表单中删除用户名。

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

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

Now, you won't see the usernamefield in the form (thanks to $builder->remove('username');). and when you submit the form, you won't get the validation error "Please enter a username"anymore because it's no longer required (thanks to the annotation).

现在,您将看不到表单中的用户名字段(感谢$builder->remove('username');)。并且当您提交表单时,您将不再收到验证错误“请输入用户名”,因为它不再需要(感谢注释)。

Source: https://github.com/FriendsOfSymfony/FOSUserBundle/issues/982#issuecomment-12931663

来源:https: //github.com/FriendsOfSymfony/FOSUserBundle/issues/982#issuecomment-12931663