Remove / Replace the username field with email using FOSUserBundle in Symfony2 / Symfony3 Remove / Replace the username field with email using FOSUserBundle in Symfony2 / Symfony3 symfony symfony

Remove / Replace the username field with email using FOSUserBundle in Symfony2 / Symfony3


A complete overview of what needs to be done

Here is a complete overview of what needs to be done. I have listed the different sources found here and there at the end of this post.

1. Override setter in Acme\UserBundle\Entity\User

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

2. Remove the username field from your form type

(in both RegistrationFormType and ProfileFormType)

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

3. Validation constraints

As shown by @nurikabe, we have to get rid of the validation constraints provided by FOSUserBundle and create our own. This means that we will have to recreate all the constraints that were previously created in FOSUserBundle and remove the ones that concern the username field. The new validation groups that we will be creating are AcmeRegistration and AcmeProfile. We are therefore completely overriding the ones provided by the FOSUserBundle.

3.a. Update config file 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. Create Validation file Acme\UserBundle\Resources\config\validation.yml

That's the long 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. End

That's it! You should be good to go!


Documents used for this post:


I was able to do this by overriding both the registration and profile form type detailed here and removing the username field

$builder->remove('username');

Along with overriding the setEmail method in my concrete user class:

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


As Michael points out, this can be solved with a custom validation group. For example:

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

Then in your entity (as defined by user_class: App\UserBundle\Entity\User) you can use the AppRegistration group:

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

This is what I ended up doing after posting that reply to the Symfony2 thread.

See http://symfony.com/doc/2.0/book/validation.html#validation-groups for full details.