2012-07-23 11 views
7

Desidero rimuovere la necessità di un nome utente in FOSUserBundle. I miei utenti accederanno usando solo un indirizzo email e ho aggiunto campi di nome reali come parte dell'entità utente. mi sono reso conto che avevo bisogno di rifare l'intera mappatura come descritto here. penso che ho fatto in modo corretto, ma quando cerco di inviare il modulo di registrazione ottengo l'errore:FOSUserBundle sovrascrive la mappatura per rimuovere la necessità di nome utente

"i nomi dei campi Solo mappato da Doctrine può essere convalidato per unicità. "

La cosa strana è che non ho provato ad applicare un vincolo univoco a qualsiasi cosa nell'entità utente.

Ecco il mio file completo dell'entità utente:

<?php 
     // src/MyApp/UserBundle/Entity/User.php 

     namespace MyApp\UserBundle\Entity; 

     use FOS\UserBundle\Model\User as BaseUser; 
     use Doctrine\ORM\Mapping as ORM; 
     use Symfony\Component\Validator\Constraints as Assert; 

     /** 
     * @ORM\Entity 
     * @ORM\Table(name="depbook_user") 
     */ 
     class User extends BaseUser 
     { 
      /** 
      * @ORM\Id 
      * @ORM\Column(type="integer") 
      * @ORM\GeneratedValue(strategy="AUTO") 
      */ 
      protected $id; 

      /** 
      * @ORM\Column(type="string", length=255) 
      * 
      * @Assert\NotBlank(message="Please enter your first name.", groups={"Registration", "Profile"}) 
      * @Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"}) 
      */ 
      protected $firstName; 

      /** 
      * @ORM\Column(type="string", length=255) 
      * 
      * @Assert\NotBlank(message="Please enter your last name.", groups={"Registration", "Profile"}) 
      * @Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"}) 
      */ 
      protected $lastName; 

      /** 
      * @ORM\Column(type="string", length=255) 
      * 
      * @Assert\NotBlank(message="Please enter your email address.", groups={"Registration", "Profile"}) 
      * @Assert\MaxLength(limit="255", message="The name is too long.", groups={"Registration", "Profile"}) 
      * @Assert\Email(groups={"Registration"}) 
      */ 
      protected $email; 

      /** 
      * @ORM\Column(type="string", length=255, name="email_canonical", unique=true) 
      */ 
      protected $emailCanonical; 

      /** 
      * @ORM\Column(type="boolean") 
      */ 
      protected $enabled; 

      /** 
      * @ORM\Column(type="string") 
      */ 
      protected $salt; 

      /** 
      * @ORM\Column(type="string") 
      */ 
      protected $password; 

      /** 
      * @ORM\Column(type="datetime", nullable=true, name="last_login") 
      */ 
      protected $lastLogin; 

      /** 
      * @ORM\Column(type="boolean") 
      */ 
      protected $locked; 

      /** 
      * @ORM\Column(type="boolean") 
      */ 
      protected $expired; 

      /** 
      * @ORM\Column(type="datetime", nullable=true, name="expires_at") 
      */ 
      protected $expiresAt; 

      /** 
      * @ORM\Column(type="string", nullable=true, name="confirmation_token") 
      */ 
      protected $confirmationToken; 

      /** 
      * @ORM\Column(type="datetime", nullable=true, name="password_requested_at") 
      */ 
      protected $passwordRequestedAt; 

      /** 
      * @ORM\Column(type="array") 
      */ 
      protected $roles; 

      /** 
      * @ORM\Column(type="boolean", name="credentials_expired") 
      */ 
      protected $credentialsExpired; 

      /** 
      * @ORM\Column(type="datetime", nullable=true, name="credentials_expired_at") 
      */ 
      protected $credentialsExpiredAt; 

      public function __construct() 
      { 
       parent::__construct(); 
       // your own logic 
      } 

      /** 
      * @return string 
      */ 
      public function getFirstName() 
      { 
       return $this->firstName; 
      } 

      /** 
      * @return string 
      */ 
      public function getLastName() 
      { 
       return $this->lastName; 
      } 

      /** 
      * Sets the first name. 
      * 
      * @param string $firstname 
      * 
      * @return User 
      */ 
      public function setFirstName($firstname) 
      { 
       $this->firstName = $firstname; 

       return $this; 
      } 

       /** 
      * Sets the last name. 
      * 
      * @param string $lastname 
      * 
      * @return User 
      */ 
      public function setLastName($lastname) 
      { 
       $this->lastName = $lastname; 

       return $this; 


     } 
    } 

Ho visto vari suggerimenti su questo, ma nessuno dei suggerimenti sembrano funzionare per me. I documenti FOSUserBundle sono molto scarsi su ciò che deve essere una richiesta molto comune.

risposta

15

Penso che il modo più semplice per farlo sia lasciare il bundle così com'è e piuttosto impostare la propria user class per avere un nome utente uguale all'indirizzo email.

A tale scopo, l'override del metodo setEmail() per impostare anche la proprietà $username al parametro $email e il setEmailCanonical() per impostare anche la $usernameCanonical al $emailCanonical.

Tutto ciò che dovrete fare diverso da questo è la semantica correlata. Come se l'etichetta del modulo avesse letto E-mail anziché l'etichetta Username predefinita. Puoi farlo sovrascrivendo i file di traduzione. Lascerò questo a te (oa qualcun altro) poiché potrebbe non essere nemmeno necessario per te.

Con questa strategia si avranno dati ridondanti nel proprio database ma si risparmierà molto rimappare il mal di testa.

+0

Stavo solo considerando di impostare un nome utente casuale solo per mantenere il fosbundle felice - ma impostare l'e-mail ha molto più senso! Soluzione semplice ed elegante! – Prathap

+5

Puoi anche chiamare 'parent :: setEmail ($ email)' dopo aver impostato 'username' (in caso di modifica del codice del bundle). Anche il metodo genitore 'return $ this;', che rende concatenabili i metodi. – Brewal

2

Se si utilizza doctrine 2, è possibile utilizzare Eventi ciclo di vita per inserire la logica in una richiamata.

http://docs.doctrine-project.org/en/2.0.x/reference/events.html

/** 
* @ORM\PreUpdate() 
* @ORM\PrePersist() 
*/ 
public function setUsernameToEmail() 
{ 
    $this->username = $this->email; 
    $this->usernameCanonical = $this->emailCanonical; 
} 
+6

Gli eventi del ciclo di vita vengono attivati ​​con l'operazione persistente. La convalida del modulo avverte comunque del nome utente vuoto. – eDoV

1

Quando non ho voglia di richiedono agli utenti di inserire messaggi di posta elettronica (e-mail rendendo così opzionali FOSUserBundle), io uso Symfony 2.7 + FOSUser + SonataUser + SonataAdmin.

Allo stesso tempo, avevo bisogno di e-mail inserite per essere uniche nel sistema. Così gli utenti hanno 2 opzioni al momento della registrazione:

  1. Leave-mail vuota
  2. Fornire un'email univoco, che non è ancora nel sistema

Qui di seguito è la mia soluzione che funziona come previsto (I don' t sostengono che sia il più pulito, ma speriamo che vi mostri un modo per realizzare un compito simile)

1) Cambia in Entità/Utente.php

namespace AppBundle\Entity; 

use Sonata\UserBundle\Entity\BaseUser as BaseUser; 
use Doctrine\ORM\Mapping as ORM; 


/** 
* @ORM\Entity 
* @ORM\Table(name="fos_user") 
* 
* 
* @ORM\AttributeOverrides({ 
*  @ORM\AttributeOverride(name="email", 
*   [email protected]\Column(
*    type = "string", 
*    name  = "email", 
*    nullable = true, 
*    unique = true 
*   ) 
*  ), 
*  @ORM\AttributeOverride(name="emailCanonical", 
*   [email protected]\Column(
*    type = "string", 
*    name  = "email_canonical", 
*    nullable = true, 
*    unique = true 
*   ) 
*  ) 
* }) 
* 
\*/ 
class User extends BaseUser 
{ 

2) Eseguiti app/console doctrine: migrazioni: diff & migrazione, tabelle di database sono stati cambiati come previsto l'aggiunta di "DEFAULT NULL" alla posta elettronica e campi email_canonical

3) No importa quello che ho provato, l'email era impostata su NULL, ma email_canonical non lo era, stava ritornando "". Ho provato a impostarlo manualmente su NULL nel mio RegistrationFormHandler, var_dump ci ha confermato che è stato effettivamente impostato su NULL quando non è stata inserita la posta elettronica. Ma al database FOSUser inviava "" una stringa vuota, che violava il vincolo UNIQUE che avevo impostato per le email, quindi la soluzione era sovrascrivere il metodo in Entity/User.php (come discusso nelle precedenti risposte a questa domanda)

// src/AppBundle/Entity/User.php 
// ... 
public function setEmailCanonical($emailCanonical) 
{ 
    // when email is empty, force canonical to NULL 
    // for some reason by default "" empty string is inserted 
    $this->emailCanonical = $this->getEmail(); 
} 

4) Cambiamento convalida per FOSUserBundle (o SonataUserBundle) nel mio caso, in modo che non sia necessario impostare la posta elettronica. (Ho semplicemente rimosso .. da validation.xml come non di quelli applicati più alla posta elettronica)

Copia questi 2 file nella tua directory config/validation/(per SonataUser + FOSUser è: Application/Sonata/UserBundle/Resources)

  1. vendor/friendsofsymfony/user-fascio/FOS/UserBundle/Resources/config/storage-validazione/orm.xml
  2. sopra percorso, config/validazione/orm.xml

Rename " Registrazione "raggruppa in questi file il tuo nome, come" miaRegistrazione ".

Associare il nuovo gruppo di validazione a fos_user in config.yml. Se si utilizza Utente Sonata, è:

sonata_user: 
    profile: 
     register: 
      form: 
       ... 
       validation_groups: 
       - myRegistration 
       - Default 

Buon divertimento.

Problemi correlati