Rimuovere / sostituire il campo del nome utente con l'e-mail utilizzando FOSUserBundle in Symfony2 / Symfony3
-
27-10-2019 - |
Domanda
Voglio solo avere la posta elettronica come modalità di accesso, non voglio avere il nome utente.È possibile con symfony2 / symfony3 e FOSUserbundle?
Ho letto qui http://groups.google.com/group/symfony2/ browse_thread / thread / 92ac92eb18b423fe
Ma poi sono bloccato con due violazioni dei vincoli.
Il problema è che se l'utente lascia vuoto l'indirizzo e-mail, ottengo due vincoli violazioni:
- Immettere un nome utente
- Inserisci un'e-mail
Esiste un modo per disabilitare la convalida per un determinato campo o un modo migliore per farlo rimuovere del tutto un campo dal modulo?
Soluzione
Una panoramica completa di ciò che deve essere fatto
Ecco una panoramica completa di ciò che deve essere fatto. Ho elencato le diverse fonti trovate qua e là alla fine di questo post.
1. Sostituisci setter in Acme\UserBundle\Entity\User
public function setEmail($email)
{
$email = is_null($email) ? '' : $email;
parent::setEmail($email);
$this->setUsername($email);
return $this;
}
2. Rimuovi il campo del nome utente dal tipo di modulo
(sia in RegistrationFormType
che in ProfileFormType
)
public function buildForm(FormBuilder $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->remove('username'); // we use email as the username
//..
}
3. Vincoli di convalida
Come mostrato da @nurikabe, dobbiamo sbarazzarci dei vincoli di convalida forniti da FOSUserBundle
e crearne uno nostro. Ciò significa che dovremo ricreare tutti i vincoli che erano stati precedentemente creati in FOSUserBundle
e rimuovere quelli che riguardano il campo username
. I nuovi gruppi di convalida che creeremo sono AcmeRegistration
e AcmeProfile
. Stiamo quindi sovrascrivendo completamente quelli forniti dal FOSUserBundle
.
3.a. Aggiorna il file di configurazione 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. Crea file di convalida Acme\UserBundle\Resources\config\validation.yml
Questa è la parte lunga:
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. Fine
Questo è tutto! Dovresti essere a posto!
Documenti utilizzati per questo post:
Altri suggerimenti
Sono stato in grado di farlo sovrascrivendo sia il tipo di modulo di registrazione che quello di profilo descritti in dettaglio qui e rimuovendo il campo nome utente
$builder->remove('username');
Oltre a sovrascrivere il metodo setEmail nella mia classe utente concreta:
public function setEmail($email)
{
$email = is_null($email) ? '' : $email;
parent::setEmail($email);
$this->setUsername($email);
}
Come sottolinea Michael, questo può essere risolto con un gruppo di convalida personalizzato.Ad esempio:
fos_user:
db_driver: orm
firewall_name: main
user_class: App\UserBundle\Entity\User
registration:
form:
type: app_user_registration
validation_groups: [AppRegistration]
Quindi nella tua entità (come definita da user_class: App\UserBundle\Entity\User
) puoi utilizzare il gruppo 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;
...
Questo è quello che ho finito per fare dopo aver postato quella risposta al thread di Symfony2.
Vedi http://symfony.com/doc/2.0/book/validation.html#validation-groups per i dettagli completi.
A partire da Sf 2.3, una soluzione rapida consiste nell'impostare il nome utente su qualsiasi stringa nella _construct della classe User che estende BaseUser.
public function __construct()
{
parent::__construct();
$this->username = 'username';
}
In questo modo, il validatore non innescherà alcuna violazione.Ma non dimenticare di impostare l'email con il nome utente pubblicato da Patt .
public function setEmail($email)
{
$email = is_null($email) ? '' : $email;
parent::setEmail($email);
$this->setUsername($email);
}
Potrebbe essere necessario controllare altri file per i riferimenti a User: username e modificare di conseguenza.
Hai provato a personalizzare la convalida?
Per fare questo, devi avere il tuo bundle che eredita da UserBundle, quindi copiare / modificare Resources / config / validation.xml.Inoltre, devi impostare validation_groups in config.yml sulla tua convalida personalizzata.
Invece di sostituire la convalida, preferisco sostituire il processo RegistrationFormHandler #, aggiungere più precisamente il nuovo metodo processExtended (ad esempio), che è una copia del metodo originale, e utilizzare ut in RegistrationController.(Sostituzione: https://github.com/FriendsOfSymfony / FOSUserBundle / blob / master / Resources / doc / index.md # next-steps )
Prima di eseguire il binding del modulo di registrazione, ho impostato il nome utente per esempio "vuoto":
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
}
Perché?Preferisco utilizzare le regole di convalida di FOSUserBundle.Perché se sostituisco Validation Group in config.yml per il modulo di registrazione, devo ripetere le regole di convalida per l'utente nella mia entità utente.
Se nessuno di loro funziona, una soluzione rapida e sporca sarebbe
public function setEmail($email)
{
$email = is_null($email) ? '' : $email;
parent::setEmail($email);
$this->setUsername(uniqid()); // We do not care about the username
return $this;
}
Puoi rendere annullabile il nome utente e quindi rimuoverlo dal tipo di modulo:
Innanzitutto , in AppBundle \ Entity \ User , aggiungi l'annotazione sopra la 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 esegui php bin/console doctrine:schema:update --force
, il nome utente annullabile nel database.
Secondo , nel tipo di modulo AppBundle \ Form \ RegistrationType , rimuovi il nome utente dal modulo.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->remove('username');
// you can add other fields with ->add('field_name')
}
Ora, non vedrai il campo nome utente nel modulo (grazie a $builder->remove('username');
).e quando invii il modulo, non riceverai più l'errore di convalida "Inserisci un nome utente" perché non è più richiesto (grazie all'annotazione).
Fonte: https://github.com/FriendsOfSymfony/FOSUserBundle/issues/ 982 # issuecomment-12931663