it-swarm-pt.tech

Restrições únicas em Doctrine 2, Symfony 2

Quero criar uma restrição exclusiva na minha entidade Doctrine 2 2, de modo que name & test sejam únicas em colunas.

  • obj1

    • nome: nome1
    • teste TESTE
  • obj2

    • name: name2
    • teste: teste <---- duplicado

Isso deve acionar um erro, pois o teste é duplicado.

Tentei usar a restrição exclusiva (Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity). Tentou

 * @UniqueEntity("name")
 * @UniqueEntity("test")

e

 * @UniqueEntity({"name", "test"})

Ambos parecem desencadear apenas erros quando eu tenho o nome e o teste duplicados. por exemplo.

  • obj1

    • nome: nome1
    • teste TESTE
  • obj2

    • name: name2
    • teste TESTE

Qual é a configuração correta? Ou eu posso ter cometido um erro em algum lugar?

Talvez eu deva incluir a anotação doctrine como:

@Table(name="ecommerce_products",uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "email"})})

Mas isso ainda não vai lidar com a validação do meu symfony, eu acho?

ATUALIZAÇÃO

Meu código de teste:

/**
 * @ORM\Entity
 * @ORM\Table(name="roles") 
 * @UniqueEntity("name")
 * @UniqueEntity("test")
 */
class Role {

    /**
     * @var integer
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @var string
     * 
     * @ORM\Column(type="string", length=32, unique=true)
     * @Assert\MaxLength(32)
     * @Assert\Regex("/^[a-zA-Z0-9_]+$/")
     */
    protected $name;

}

$v = $this->get('validator');

$role = new Role();
$role->setName('jm');
$role->setTest('test');
$e = $v->validate($role);
echo '=== 1 ===';
var_dump($e);
if (count($e) == 0)
    $em->persist($role);            

$role2 = new Role();
$role2->setName('john');
$role2->setTest('test');
$e = $v->validate($role2);
echo '=== 2 ===';
var_dump($e);
if (count($e) == 0)
    $em->persist($role2);

$em->flush();

Na primeira execução (tabela vazia):

=== 1 ===object(Symfony\Component\Validator\ConstraintViolationList)#322 (1) {
  ["violations":protected]=>
  array(0) {
  }
}
=== 2 ===object(Symfony\Component\Validator\ConstraintViolationList)#289 (1) {
  ["violations":protected]=>
  array(0) {
  }
}

Mas eu recebo um erro na camada de banco de dados sobre restrição exclusiva. Então, como devo fazer com que a camada de validação funcione?

29
Jiew Meng

Eles verificam os campos individualmente:

@UniqueEntity("name")
@UniqueEntity("test")

Ou seja, o primeiro será acionado quando houver um valor duplicado name, enquanto o segundo - quando houver um valor duplicado test.

Se você deseja que a validação falhe quando ambos name e test contêm o mesmo combinação , você usa isto:

@UniqueEntity({"name", "test"})

Para o que você deseja, a primeira abordagem deve funcionar - a menos que você tenha feito algo errado em outro lugar. Tente também limpar o cache para garantir que não é culpa dele.

ATUALIZAÇÃO

O que sugeri foi sobre a parte de validação no lado do aplicativo. Se você gerar o esquema do banco de dados usando o Doctrine, precisará fornecer as anotações de nível Doctrine $ para cada coluna - se você quiser torná-los únicos independentemente um do outro, é claro:

@Column(type = "string", unique = true)
private $name;

@Column(type = "string", unique = true)
private $test;

Essas abordagens se complementam - não excluem. @UniqueEntity garante que uma duplicata nem alcance a camada do banco de dados, enquanto @Column garante que, se houver, a camada do banco de dados não deixará passar.

50
Elnur Abdurrakhimov

Na anotação de tabela, você também pode definir um índice para vários colunas .

/** 
 * @ORM\Entity 
 * @ORM\Table (nome = "produtos de comércio eletrônico", uniqueConstraints = {
 * @ORM\UniqueConstraint (nome = "search_idx", colunas = {"nome", "email"})}) 
 */

ou com o formato YAML:

Namespace\Entity\EntityName:
    type: entity
    table: ecommerce_products
    uniqueConstraints:
        uniqueConstraint:
            columns: [name, email]
50
yvoyer