Remover / Substituir o campo de nome de usuário com e-mail usando FOSUserBundle no Symfony2 / Symfony3
-
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?
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