2011-12-13 13 views
5

Próbuję zweryfikować unikalność jednostki przesłanej z formularza za pomocą wiązania UniqueEntity Validation na wielu polach.Symfony2 UniqueEntity multiple fields: false positive validation?

Kod jednostki, która powinna być unikalna ma dwa pola - fieldA i fieldB, zarówno wyjątkowy:

/** 
* @ORM\Table(name="mytable") 
* @ORM\Entity 
* @DoctrineAssert\UniqueEntity(fields = {"fieldA", "fieldB"}) 
*/ 
class myClass 
{ 
    /** 
    * @ORM\Column(name="fieldA", type="string", length=128, unique=true) 
    */ 
    protected $fieldA; 

    /** 
    * @ORM\Column(name="fieldB", type="string", length=128, unique=true) 
    */ 
    protected $fieldB; 
} 

Załóżmy mam już rekord w bazie danych o wartościach:

  • pole A = "wartość_a", poleB = "wartość_b"

Teraz, gdy próbuję przedstawić jeszcze jeden z wartościami (fieldA = „value_a”, fieldB = „value_c”) z postaci, Symfony2 generuje zapytanie by sprawdzić unikalność:

SELECT ... FROM ... WHERE fieldA = ? AND fieldB = ? ('value_a', 'value_c') 

a walidacja przechodzi, ponieważ wynikiem jest pusty zestaw, ale Spodziewam się, że się nie uda, ponieważ pole A nie będzie unikalne w tym przypadku. (SQL insert nie powiedzie się z duplikatu błędu wejścia na „value_a”).

Symfony2's UniqueEntity documentation says:

Ta opcja jest wymagane pole (lub lista pól), na którym podmiot ten powinien być unikalny. Na przykład możesz określić, że zarówno adres e-mail, jak i pola nazwy w powyższym przykładzie User powinny być unikalne.

Myślę, że to potwierdza moje oczekiwania.

Dowiedziałem się, że in the source of UniqueEntityValidator (line 94), że walidator bierze pola jako tablicę, i używa metody "findBy", aby sprawdzić unikalność. Ta metoda używa relacji "AND" między parametrami w zapytaniu, co powoduje problem.

Czy można w jakikolwiek sposób wykorzystać to ograniczenie sprawdzające dla mojego problemu, czy muszę go zatwierdzić w inny sposób?

Odpowiedz

8

Co o:

/** 
* @ORM\Table(name="mytable") 
* @ORM\Entity 
* @DoctrineAssert\UniqueEntity(fields = "fieldA") 
* @DoctrineAssert\UniqueEntity(fields = "fieldB") 
*/ 
class myClass 

?

+0

Dziękuję, że spełnia swoje zadanie! Jedyny problem polega na tym, że każde stwierdzenie przyjmuje kolejne zapytanie, ale myślę, że mogę z tym żyć. – csabavegso

+1

W przeciwnym razie zawsze masz rozwiązanie, aby napisać własny Validator, inspirowany przez UniqueEntity Validator – webda2l

13

Powinno być:

/** 
* @ORM\Table(name="mytable") 
* @ORM\Entity 
* @DoctrineAssert\UniqueEntity(fields = "fieldA") 
* @DoctrineAssert\UniqueEntity(fields = "fieldB") 
*/ 
class myClass 

Robiąc

* @DoctrineAssert\UniqueEntity(fields = {"fieldA", "fieldB"}) 

będzie sprawdzić, czy nie ma żadnych wierszy z obu pól to samo.

Więc załóżmy, masz już rekord w bazie o wartości:

fieldA = 'value_a', fieldB = 'value_b' 

Teraz podczas próby do przedstawienia jeszcze jeden z wartościami (fieldA = „value_a”, fieldB = „value_c”) z formularza Symfony2 generuje zapytanie sprawdzające wyjątkowość:

WYBIERZ ... Z ... GDZIE pole A =?AND fieldB =? ('Value_a', 'value_c')

i Przepuszcza, bo nie pasuje do wiersza z

fieldA = 'value_a', fieldB = 'value_b' 

tylko po jo przedstawić inny z wartościami (fieldA = 'value_a' fieldB = "value_b") z formularza, sprawdzanie poprawności nie przejdzie.

ten sposób powinno działać i jak to jest opisane w dokumentacji: http://symfony.com/doc/current/reference/constraints/UniqueEntity.html#fields