Retire / reemplace el campo Nombre de usuario con correo electrónico usando FosuserBundle en Symfony2 / Symfony3

StackOverflow https://stackoverflow.com/questions/8832916

  •  27-10-2019
  •  | 
  •  

Pregunta

Solo quiero tener correo electrónico como modo de inicio de sesión, no quiero tener nombre de usuario. ¿Es posible con Symfony2/Symfony3 y FosuserBundle?

Leí aquí http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe

Pero luego estoy atrapado con dos violaciones de restricción.

El problema es que si el usuario deja en blanco la dirección de correo electrónico, obtengo dos violaciones de restricción:

  • por favor, ingrese un nombre de usuario
  • Ingrese un correo electrónico

¿Hay alguna forma de deshabilitar la validación para un campo determinado, o una mejor manera de eliminar un campo de la forma por completo?

¿Fue útil?

Solución

Una descripción completa de lo que hay que hacer

Aquí hay una descripción completa de lo que hay que hacer. He enumerado las diferentes fuentes que se encuentran aquí y allá al final de esta publicación.

1. Anular el setter en Acme\UserBundle\Entity\User

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

    return $this;
}

2. Elimine el campo Nombre de usuario de su tipo de formulario

(en ambos RegistrationFormType y ProfileFormType)

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

3. Restricciones de validación

Como se muestra en @nurikabe, tenemos que deshacernos de las limitaciones de validación proporcionadas por FOSUserBundle y crear el nuestro. Esto significa que tendremos que recrear todas las limitaciones que se crearon previamente en FOSUserBundle y eliminar los que se refieren al username campo. Los nuevos grupos de validación que estaremos creando son AcmeRegistration y AcmeProfile. Por lo tanto, estamos anulando por completo los proporcionados por el FOSUserBundle.

3.A. Actualizar el archivo de configuración en 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. Crear archivo de validación Acme\UserBundle\Resources\config\validation.yml

Ese es lo largo:

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

¡Eso es todo! ¡Usted debe ser bueno para ir!


Documentos utilizados para esta publicación:

Otros consejos

Pude hacer esto anulando tanto el registro como el tipo de perfil de forma detallada aquí y eliminar el campo de nombre de usuario

$builder->remove('username');

Junto con la anulación del método SetEmail en mi clase de usuario concreto:

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

Como señala Michael, esto se puede resolver con un grupo de validación personalizado. Por ejemplo:

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

Luego en tu entidad (como se define por user_class: App\UserBundle\Entity\User) puede usar el grupo de apregistraciones:

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

Esto es lo que terminé haciendo después de publicar esa respuesta al hilo Symfony2.

Ver http://symfony.com/doc/2.0/book/validation.html#validation-groups Para detalles completos.

A partir de SF 2.3, un Solución rápida es establecer el nombre de usuario en cualquier cadena en la _construcción de su usuario de su clase que extienda BaseUser.

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

De esta manera, el validador no desencadena ninguna violación. Pero no olvide establecer el correo electrónico en el nombre de usuario como se publica por Empatan.

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

Es posible que deba consultar otros archivos para ver las referencias al usuario: nombre de usuario y cambiar en consecuencia.

¿Has intentado personalizar la validación?

Para hacer esto, debe hacer que su propio paquete herede del UserBundle y luego copie/ajuste los recursos/config/validation.xml. Además, debe establecer la validación_groups en config.yml en su validación personalizada.

En lugar de reemplazar la validación, prefiero reemplazar el proceso de registroformhandler#, agregar con mayor precisión el nuevo método ProcessExtended (por ejemplo), que es una copia del método original, y use UT en RegistrationController. (Primordial: https://github.com/friendsofsymfony/fosuserbundle/blob/master/resources/doc/index.md#nextsteps)

Antes de que vincule el formulario de registro, configuré el nombre de usuario, por ejemplo, 'vacío':

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
}

¿Por qué? Prefiero las reglas de validación del usuario FosuserBundle. Porque si reemplazo el grupo de validación en config.yml para el formulario de registro, necesito repetir las reglas de validación para el usuario en mi propia entidad de usuario.

Si ninguno de ellos funciona, una solución rápida y sucia sería

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

    return $this;
}

Puede hacer que el nombre de usuario sea anulable y luego eliminarlo del tipo de formulario:

Primero, en Appbundle entity user, agregue la anotación por encima de la clase de usuario

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

Cuando corres php bin/console doctrine:schema:update --force Hará que el nombre de usuario sea anulable en la base de datos.

Segundo, en tu tipo de forma AppBundle Form RegistrationType, elimine el nombre de usuario del formulario.

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

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

Ahora no verás el nombre de usuario campo en el formulario (gracias a $builder->remove('username');). y cuando envíe el formulario, no recibirá el error de validación "Por favor, ingrese un nombre de usuario" Más porque ya no es necesario (gracias a la anotación).

Fuente: https://github.com/friendsofsymfony/fosuserbundle/issues/982#issuecomment-12931663

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top