Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Aspectos a tener en cuenta en los Entity Constraints

8 de diciembre de 2013

Quería compartir la solución con aquellos que hayais tenido el problema que he tenido yo con hacer único un atributo de una entidad, como era mi caso con el atributo email en mi entidad USUARIO.

Siguiendo la documentación añadí en mi entidad las siguientes líneas para que al usuario que quisiera registrarse con un email utilizado le saltase una excepción en el formulario advirtiéndoselo:

use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
 
/**
 * @ORM\Entity
 * @UniqueEntity("email")
 */
class Usuario implements AdvancedUserInterface
{
 
    // ...
 
    /**
     * @var string
     *
     * @ORM\Column(name="email", type="string", length=255, unique=true)
     * @Assert\Email()
     */
    protected $email;

Haciendo lo anterior, no llegaba a conseguir mi propósito ya que cuando intentaba registrarme con un email ya existente, me saltaba una excepción no controlada de tipo DuplicateEntry y que en ningún caso era lo que quería:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
                 '[email protected]' for key 'UNIQ_D8183973E7927C74'

Tras investigar he dado con la solución que pretendía, que era ni más ni menos que saltara un mensaje en el formulario del registro. Para lo anterior hay que modificar la línea del UniqueEntity de la siguiente forma:

/**
 * @ORM\Entity
 * * @UniqueEntity(fields={"email"}, message="Este correo ya está siendo utilizado",
 *                 groups={"registro"})
 */
class Usuario implements AdvancedUserInterface
{
    // ...
}

Siendo registro el nombre que le hayamos dado al validation_groups de la función setDefaultOptions que tenemos implementado en el formType.

Además, para aquellos que estén usando formularios embebidos, para hacer funcionar el @UniqueEntity debéis añadir al método setDefaultOptions mencionado la siguiente línea:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        // ...
        'cascade_validation' => true,
    ));
}

Respuestas

#1

Con symfony2.2 igual me ocurre con

@Assert\Callback(methods={"formatoEmailCorrecto"})

que lo he debido cambiar a

@Assert\Callback(methods={"formatoEmailCorrecto"}, groups={"registro"})

para que realmente me funcione.

@Jorge_Gante

9 diciembre 2013, 23:36
#2

@Jorge_Gante creo que en este caso realmente no estamos hablando de un bug, sino de un pequeño desajuste en las anotaciones de la entidad. Por el código que muestras, supongo que validas la entidad con un código como el siguiente:

$validator->validate($usuario, array('registro'));

Sin embargo, en tu primer ejemplo la anotación estaba configurada de la siguiente manera:

/**
 * @ORM\Entity
 * @UniqueEntity("email")
 */
class Usuario implements AdvancedUserInterface
{
    // ...
}

Cuando una constraint de validación no tiene asignada un grupo, se supone que pertenece al grupo default. Así que la restricción que hace que el email no pueda estar duplicado, pertenece al grupo default y no al grupo registro. Cuando validas la entidad con el código anterior, sólo se ejecutan las restricciones del grupo registro, por lo que la restricción @UniqueEntity no es que esté funcionando mal, es que ni siquiera se está ejecutando.

@javiereguiluz

10 diciembre 2013, 8:33
#3

Me he expresado mal, no es un bug. Más bien es una aspecto a tener en cuenta para hacer funcionar las constraint de validación de las entidades.

@Jorge_Gante

10 diciembre 2013, 10:42