web-dev-qa-db-fra.com

Supprimer / remplacer le champ du nom d'utilisateur par e-mail à l'aide de FOSUserBundle dans Symfony2 / Symfony3

Je veux seulement avoir le courrier électronique comme mode de connexion, je ne veux pas avoir de nom d'utilisateur. Est-ce possible avec symfony2/symfony3 et FOSUserbundle?

J'ai lu ici http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

Mais alors je suis coincé avec deux violations de contraintes.

Le problème est que si l'utilisateur laisse l'adresse e-mail vide, j'obtiens deux violations de contrainte:

  • Merci d'entrer un nom d'utilisateur
  • Veuillez saisir un e-mail

Existe-t-il un moyen de désactiver la validation pour un champ donné ou un meilleur moyen de supprimer un champ du formulaire?

57
user825904

Un aperçu complet de ce qui doit être fait

Voici un aperçu complet de ce qui doit être fait. J'ai énuméré les différentes sources trouvées ici et là à la fin de ce post.

1. Ignorer le setter dans Acme\UserBundle\Entity\User

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

    return $this;
}

2. Supprimez le champ du nom d'utilisateur de votre type de formulaire

(dans les deux RegistrationFormType et ProfileFormType)

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

3. Contraintes de validation

Comme le montre @nurikabe, nous devons nous débarrasser des contraintes de validation fournies par FOSUserBundle et créer les nôtres. Cela signifie que nous devrons recréer toutes les contraintes précédemment créées dans FOSUserBundle et supprimer celles qui concernent le champ username. Les nouveaux groupes de validation que nous allons créer sont AcmeRegistration et AcmeProfile. Nous remplaçons donc complètement ceux fournis par le FOSUserBundle.

3.a. Mettre à jour le fichier de configuration dans 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. Créer un fichier de validation Acme\UserBundle\Resources\config\validation.yml

C'est le long morceau:

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. Fin

C'est ça! Vous devriez être prêt à partir!


Documents utilisés pour ce message:

104
Mick

J'ai pu le faire en remplaçant à la fois l'inscription et le type de profil détaillé ici et en supprimant le champ du nom d'utilisateur

$builder->remove('username');

En plus de remplacer la méthode setEmail dans ma classe d'utilisateurs concrète:

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

Depuis Sf 2.3, une solution de contournement rapide consiste à définir le nom d'utilisateur sur n'importe quelle chaîne de la _construct de votre classe User qui étend BaseUser.

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

De cette façon, le validateur ne déclenchera aucune violation. Mais n'oubliez pas de définir l'e-mail sur le nom d'utilisateur tel que publié par Patt .

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

Vous devrez peut-être vérifier les autres fichiers pour les références à User: nom d'utilisateur et modifier en conséquence.

2
iambray

Comme Michael le fait remarquer, cela peut être résolu avec un groupe de validation personnalisé. Par exemple:

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

Puis dans votre entité (telle que définie par user_class: App\UserBundle\Entity\User) vous pouvez utiliser le groupe 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;
    ...

C'est ce que j'ai fini par faire après avoir posté cette réponse sur le fil Symfony2.

Voir http://symfony.com/doc/2.0/book/validation.html#validation-groups pour plus de détails.

2
nurikabe

Avez-vous essayé de personnaliser la validation?

Pour ce faire, vous devez avoir votre propre bundle héritant de UserBundle, puis copier/ajuster Resources/config/validation.xml. De plus, vous devez définir les validation_groups dans le config.yml sur votre validation personnalisée.

1
Michael Sauter

Au lieu de remplacer Validation, je préfère remplacer le processus RegistrationFormHandler #, ajoutez plus précisément la nouvelle méthode processExtended (par exemple), qui est une copie de la méthode d'origine, et utilisez ut dans RegistrationController. (Substitution: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps )

Avant de lier le formulaire d'inscription, je définis le nom d'utilisateur par exemple "vide":

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
}

Pourquoi? Je préfère utiliser les règles de validation FOSUserBundle. Parce que si je remplace le groupe de validation dans config.yml pour le formulaire d'inscription, je dois répéter les règles de validation pour l'utilisateur dans ma propre entité utilisateur.

1
ZloyPotroh

Si aucun d'entre eux ne fonctionne, une solution rapide et sale serait

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

    return $this;
}
1
getvivekv

Vous pouvez rendre le nom d'utilisateur nul et le supprimer du type de formulaire:

Tout d'abord , dans AppBundle\Entity\User , ajoutez l'annotation au-dessus du Classe d'utilisateurs

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
{
//..

Lorsque vous exécutez php bin/console doctrine:schema:update --force, Le nom d'utilisateur sera annulable dans la base de données.

Deuxièmement , dans votre type de formulaire AppBundle\Form\RegistrationType , supprimez le nom d'utilisateur du formulaire.

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

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

Maintenant, vous ne verrez pas le champ username dans le formulaire (grâce à $builder->remove('username');). et lorsque vous soumettez le formulaire, vous n'obtiendrez pas l'erreur de validation "Veuillez saisir un nom d'utilisateur" car il n'est plus nécessaire (grâce à l'annotation).

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

0
Eissa