Remover / Substituir o campo de nome de usuário com e-mail usando FOSUserBundle no Symfony2 / Symfony3

StackOverflow https://stackoverflow.com/questions/8832916

  •  27-10-2019
  •  | 
  •  

Pergunta

Eu só quero ter o e-mail como modo de início de sessão, eu não quero ter nome de usuário.Isso é possível com o symfony2/symfony3 e FOSUserbundle?

Eu li aqui http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

Mas então eu estou preso com duas violações de restrição.

O problema é que o usuário deixa o endereço de e-mail em branco, eu tenho duas restrição violações:

  • Por favor introduza um nome de utilizador
  • Por favor digite um e-mail

Existe uma maneira de desabilitar a validação de um determinado campo, ou uma maneira melhor para remover um campo do formulário por completo?

Foi útil?

Solução

Uma visão completa do que precisa ser feito

Aqui está uma visão geral e completa do que precisa ser feito.Eu listei as diferentes fontes encontradas aqui e ali no final deste post.

1.Substituir setter, em Acme\UserBundle\Entity\User

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

    return $this;
}

2.Remova o campo nome de usuário do seu tipo de formulário

(em ambos os RegistrationFormType e ProfileFormType)

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

3.Validação de restrições

Como mostrado por @nurikabe, temos de nos livrar da validação de restrições fornecidas pela FOSUserBundle e criar o nosso próprio.Isso significa que vamos ter de recriar todas as restrições que foram criados anteriormente em FOSUserBundle e remover aqueles que dizem respeito a username de campo.A nova validação grupos que estaremos criando estão AcmeRegistration e AcmeProfile.Estamos, portanto, substituir completamente o fornecido pela FOSUserBundle.

3.um.Atualização do arquivo de configuração em 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.Criar arquivo de Validação Acme\UserBundle\Resources\config\validation.yml

Esse é o tempo de 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.Fim

Que é isso!Você deve ser bom para ir!


Os documentos utilizados para este post:

Outras dicas

Consegui fazer isso substituindo o registro e o tipo de formulário de perfil detalhado aqui e removendo o campo de nome de usuário

$builder->remove('username');

Além de substituir o método setEmail em minha classe de usuário concreta:

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

Como Michael aponta, isso pode ser resolvido com um grupo de validação personalizado.Por exemplo:

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

Então, em sua entidade (conforme definido por user_class: App\UserBundle\Entity\User), você pode usar o grupo 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;
    ...

Isso é o que acabei fazendo depois de postar aquela resposta no tópico do Symfony2.

Consulte http://symfony.com/doc/2.0/book/validation.html#validation-groups para detalhes completos.

A partir do Sf 2.3, uma solução alternativa rápida é definir o nome de usuário como qualquer string no _construct de sua classe User que estende BaseUser.

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

Dessa forma, o validador não acionará nenhuma violação.Mas não se esqueça de definir o e-mail com o nome de usuário postado por Patt .

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

Você pode ter que verificar outros arquivos para referências a Usuário: nome de usuário e alterar de acordo.

Você já tentou personalizar a validação?

Para fazer isso, você precisa ter seu próprio pacote herdado do UserBundle e, em seguida, copiar / ajustar Resources / config / validation.xml.Além disso, você precisa definir o validation_groups no config.yml para sua validação personalizada.

Em vez da substituição da Validação, prefiro substituir RegistrationFormHandler # process, mais precisamente adicionar o novo método processExtended (por exemplo), que é uma cópia do método original, e usar ut em RegistrationController.(Substituindo: https://github.com/FriendsOfSymfony / FOSUserBundle / blob / master / Resources / doc / index.md # next-steps )

Antes de vincular o formulário de registro, defino o nome de usuário por exemplo 'vazio':

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
}

Por quê?Eu prefiro usar regras de validação FOSUserBundle.Porque se eu substituir o Grupo de validação em config.yml para o formulário de registro, eu preciso repetir as regras de validação para o usuário em minha própria entidade de usuário.

Se nenhum deles funcionar, uma solução rápida e suja seria

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

    return $this;
}

Você pode tornar o nome de usuário anulável e removê-lo do tipo de formulário:

Primeiro , em AppBundle \ Entity \ User , adicione a anotação acima da classe 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
{
//..

Quando você executa php bin/console doctrine:schema:update --force, ele torna o nome de usuário anulável no banco de dados.

Em segundo lugar , no tipo de formulário AppBundle \ Form \ RegistrationType , remova o nome de usuário do formulário.

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

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

Agora, você não verá o campo nome de usuário no formulário (graças a $builder->remove('username');).e quando enviar o formulário, você não receberá mais o erro de validação "Digite um nome de usuário" porque não é mais necessário (graças à anotação).

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top