11

I am trying to remove the unique index on emailCanonical, so that multiple users can share the same email address. However, I do not want to edit FOS/UserBundle/Resources/config/doctrine/User.orm.xml directly as any updates to the bundle itself will remove the change. Is there any way I can override the emailCanonical field in my own bundle, while extending the base user (FOS/UserBundle/Model/User.php)

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Foo\BarBundle\Constant\SecurityConstant;

class User extends BaseUser {
    protected $id;
...
}

Thanks in advance!

Otto Yiu
  • 265
  • 1
  • 4
  • 13

3 Answers3

41

The answer that is marked as right now (14 Oct 2014) is not the right answer at all.

This is the only right solution:

namespace XXX\UserBundle\Entity;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Entity
 * @ORM\Table(name="User_User")
 * @ORM\Entity(repositoryClass="UserRepository")
 * @UniqueEntity(fields="usernameCanonical", errorPath="username", message="fos_user.username.already_used")
 * @ORM\AttributeOverrides({
 *      @ORM\AttributeOverride(name="email", column=@ORM\Column(type="string", name="email", length=255, unique=false, nullable=true)),
 *      @ORM\AttributeOverride(name="emailCanonical", column=@ORM\Column(type="string", name="email_canonical", length=255, unique=false, nullable=true))
 * })
 */
class User extends BaseUser
{
...
}

Also you need to override validation groups for your user form:

# app/config/config.yml
...
fos_user:
profile:
    form:
        validation_groups:  [Default] # Here you can also add your own groups if you have extra validation
registration:
    form:
        validation_groups:  [Default] # Here you can also add your own groups if you have extra validation

What did we do? We just overrode validation groups to not match the FOS default validations. Instead your form will be validated only with Default group. Described above validation UniqueEntity that doesn't have any group will be matched by Default group.

Michael Sivolobov
  • 12,388
  • 3
  • 43
  • 64
Tim
  • 1,238
  • 1
  • 14
  • 24
  • name="email_canonical", ... name="username_canonical" should do the job. – jrg Jun 24 '14 at 10:53
  • I modified the answer, add some more explanations. And now it works in any versions of Symfony and FOSUserBundle that are yet maintained. – Michael Sivolobov Oct 14 '14 at 04:54
  • 2
    Be carefull because only the first user will be able to reset it's password with the email. – Lou Terrailloune Oct 17 '14 at 21:35
  • 2
    This gives me an error: `Invalid field override named 'email'`. Somehow, `ClassMetadataInfo::fieldMappings` only contains the fields of the child class, and not the parent class (which contains the email field I want to override). This error is only thrown when generating entities. – Thomas K Nov 19 '14 at 15:18
7

The only way to do this is to extend the FOS\UserBundle\Model\User class and then re-do all of the mapping (everything in User.orm.xml) yourself.

Sources:

leek
  • 11,803
  • 8
  • 45
  • 61
  • 1
    A better solution is the Tim's answer – Arno Jul 31 '17 at 14:25
  • Thanks @Arno - at the time of writing (~2011), this answer was correct since `@ORM\AttributeOverride` didn't exist. Anyone who comes across this question now should check out [@Tim's answer](https://stackoverflow.com/a/17059918/3765) below. – leek Aug 17 '17 at 21:51
1

Supplement to Tim's answer, this is how you'd do it using YAML:

My\UserBundle\Entity\User:
    type: entity
    table: null
    repositoryClass: My\UserBundle\Entity\UserRepository
    attributeOverride:
      usernameCanonical:
        unique: false
        name: usernameCanonical
        column: username_canonical
        length: 255
        nullable: false
        type: string
      emailCanonical:
        unique: false
        name: emailCanonical
        column: email_canonical
        length: 255
        nullable: false
        type: string
    fields:
        id:
          type: integer
          id: true
          generator:
              strategy: AUTO
        firstName:
          type: string
          length: 255
Machiel
  • 1,495
  • 12
  • 15