web-dev-qa-db-fra.com

Contraintes uniques dans Doctrine 2, Symfony 2

Je veux créer une contrainte unique dans mon Doctrine 2 entité de telle sorte que name & test sont des colonnes uniques. Signification

  • obj1

    • nom: nom1
    • test: test
  • obj2

    • nom: nom2
    • test: test <---- dupliqué

Cela devrait déclencher une erreur lorsque le test est dupliqué.

J'ai essayé d'utiliser la contrainte unique (Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity). A tenté

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

et

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

Les deux semblent déclencher une erreur uniquement lorsque j'ai le nom et le test en double. par exemple.

  • obj1

    • nom: nom1
    • test: test
  • obj2

    • nom: nom2
    • test: test

Quelle est la bonne configuration? Ou j'ai peut-être fait une erreur quelque part?

Je devrais peut-être inclure l'annotation doctrine comme:

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

Mais cela ne gérera toujours pas ma validation de formulaire symfony je pense?

MISE À JOUR

Mon code de test:

/**
 * @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();

Lors de la première exécution (table vide):

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

Mais j'obtiens une erreur sur la couche de base de données sur la contrainte unique. Alors, comment dois-je faire fonctionner la couche de validation?

29
Jiew Meng

Ceux-ci vérifient les champs individuellement:

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

Autrement dit, le premier sera déclenché lorsqu'il y a une valeur name en double, tandis que le second - lorsqu'il y a une valeur test en double.

Si vous voulez que la validation échoue lorsque les deux name et test contiennent les mêmes combinaison , vous utilisez ceci:

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

Pour ce que vous voulez, la première approche devrait fonctionner - sauf si vous avez fait quelque chose de mal ailleurs. Essayez également de vider le cache pour vous assurer que ce n'est pas de sa faute.

MISE À JOUR

Ce que j'ai suggéré concernait la partie validation du côté de l'application. Si vous générez le schéma de base de données à l'aide de Doctrine, vous devrez fournir les annotations de niveau Doctrine) pour chaque colonne - si vous voulez les rendre uniques indépendamment les uns des autres, bien sûr:

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

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

Ces approches se complètent - ne s'excluent pas. @UniqueEntity s'assure qu'un doublon n'atteint même pas la couche de base de données, tandis que @Column garantit que si c'est le cas, la couche de base de données ne la laissera pas passer.

50
Elnur Abdurrakhimov

Dans l'annotation Table, vous pouvez également définir un index pour plusieurs colonnes .

/** 
 * @ORM\Entity 
 * @ORM\Table (name = "ecommerce_products", uniqueConstraints = {
 * @ORM\UniqueConstraint (name = "search_idx", colonnes = {"nom", "email"})}) 
 */

ou au format YAML:

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