56

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

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

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

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

  • 请填入一个用户名
  • 请输入电子邮件

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

4

8 回答 8

103

需要做什么的完整概述

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

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字段相关的约束。我们将创建的新验证组是AcmeRegistrationAcmeProfile。因此,我们完全覆盖了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.结束

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


本帖使用的文件:

于 2014-01-11T16:15:31.633 回答
7

我可以通过覆盖此处详述的注册和个人资料表单类型并删除用户名字段来做到这一点

$builder->remove('username');

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

 public function setEmail($email) 
 {
    $email = is_null($email) ? '' : $email;
    parent::setEmail($email);
    $this->setUsername($email);
  }
于 2015-03-11T23:37:53.357 回答
2

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

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

于 2012-01-12T13:41:53.983 回答
2

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

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 的引用并进行相应更改。

于 2014-10-02T18:55:08.493 回答
1

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

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

于 2012-01-12T11:51:10.843 回答
1

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

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

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
}

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

于 2012-09-24T11:39:14.993 回答
1

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

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

    return $this;
}
于 2016-05-29T17:04:06.627 回答
0

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

首先,在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
{
//..

当您运行时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

于 2019-07-16T11:30:38.670 回答