2012-07-23 19 views
7

Deseo eliminar la necesidad de un nombre de usuario en FOSUserBundle. Mis usuarios iniciarán sesión solo con una dirección de correo electrónico y agregué campos de nombre real como parte de la entidad de usuario. me di cuenta que tenía que volver a hacer todo el mapeo como se describe here. Creo que lo he hecho correctamente, pero cuando trato de enviar el formulario de inscripción consigo el error:FOSUserBundle anula la asignación para eliminar la necesidad de nombre de usuario

nombres "único campo asignado por la doctrina puede ser validado por singularidad ".

Lo extraño es que no he intentado imponer una restricción única a nada en la entidad de usuario.

Aquí está mi archivo completo entidad de usuario:

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


     } 
    } 

que he visto varias sugerencias acerca de esto, pero ninguna de las sugerencias parece funcionar para mí. Los documentos de FOSUserBundle son muy escasos sobre lo que debe ser una solicitud muy común.

Respuesta

15

Creo que la manera más fácil de hacerlo es dejar el paquete tal como está y configurar su clase de usuario para que tenga un nombre de usuario igual a la dirección de correo electrónico.

hacer esto mediante la sustitución del método setEmail() configurar también la propiedad $username al parámetro $email y la setEmailCanonical() para ajustar también la $usernameCanonical a la $emailCanonical.

public function setEmail($email){ 
    $this->email = $email; 
    $this->username = $email; 
} 

public function setEmailCanonical($emailCanonical){ 
    $this->emailCanonical = $emailCanonical; 
    $this->usernameCanonical = $emailCanonical; 
} 

Todo lo que tendrás que hacer aparte de esto es la semántica relacionada. Al igual que con la etiqueta de su formulario, lea el correo electrónico en lugar de la etiqueta predeterminada de nombre de usuario. Puede hacerlo anulando los archivos de traducción. Dejaré esto a usted (u otra persona) ya que puede que ni siquiera sea necesario para usted.

Con esta estrategia, tendrá datos redundantes en su base de datos, pero le ahorrará muchos dolores de cabeza de reasignación.

+0

Estaba considerando la posibilidad de establecer un nombre de usuario aleatorio solo para mantener al fósil feliz, pero configurar el correo electrónico tiene mucho más sentido. ¡Solución simple y elegante! – Prathap

+5

También puede llamar a 'parent :: setEmail ($ email)' después de configurar 'username' (en caso de un cambio en el código del paquete). El método principal también 'return $ this;', lo que hace que los métodos sean encadenables. – Brewal

2

Si está utilizando la doctrina 2, puede usar Eventos del ciclo de vida para poner su lógica dentro de una devolución de llamada.

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

Los eventos del ciclo de vida se activan en la operación persistir. La validación del formulario todavía advertirá sobre el nombre de usuario vacío. – eDoV

1

Cuando yo no quiero requieren que los usuarios introduzcan correos electrónicos (e-mails con lo opcionales en FOSUserBundle), que utiliza Symfony 2.7 + + FOSUser SonataUser + SonataAdmin.

Al mismo tiempo, necesitaba que los correos electrónicos ingresados ​​fueran únicos en el sistema. Así, los usuarios tienen 2 opciones al registrarse:

  1. Dejar correo en blanco
  2. introduce un correo electrónico único, que aún no ha entrado en el sistema

A continuación es mi solución que funciona como se esperaba (I don' t afirmar que es el más limpio, pero con suerte le mostrará una manera de cómo llevar a cabo una tarea similar)

1) Cambios en la entidad/usuario.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) ejecutadas doctrina app/consola: migraciones: diff & emigrar, tablas de bases se cambiaron como se esperaba añadiendo "DEFAULT NULL" al correo electrónico y campos email_canonical

3) n importa lo que intenté, el correo electrónico se estaba estableciendo en NULL, pero email_canonical no, estaba regresando "". Intenté configurarlo manualmente en NULL en mi RegistrationFormHandler, var_dump allí confirmó que efectivamente estaba en NULL cuando no se ingresó el correo electrónico. Pero a la base de datos, FOSUser enviaría "" una cadena vacía, que violaba la restricción ÚNICA que había establecido para los correos electrónicos, por lo que la solución era anular el método en Entity/User.php (como se discutió en las respuestas anteriores)

// 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) Validación de cambio para FOSUserBundle (o SonataUserBundle) en mi caso, para que no requiera que se establezca el correo electrónico. (Simplemente eliminé ... de validation.xml como no aplicado al correo electrónico)

Copie estos 2 archivos en su configuración/validación/directorio (para SonataUser + FOSUser es: Aplicación/Sonata/UserBundle/Resources)

  1. vendedor/friendsofsymfony/usuario de haz/FOS/UserBundle/Recursos/config/almacenamiento de validación/orm.xml
  2. encima de trayectoria, config/validación/orm.xml

Cambiar nombre " Registro "agrupe en esos archivos a su propio nombre, como" myRegistration ".

Enlaza tu nuevo validación_grupo a fos_user en config.yml. Si usa Sonata User, es:

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

Have fun.

Cuestiones relacionadas