Symfony2 UniqueEntity несколько полей: ложное положительное подтверждение? - PullRequest
6 голосов
/ 13 декабря 2011

Я пытаюсь проверить уникальность сущности, отправленной из формы, используя ограничение проверки уникальности для нескольких полей.

Код объекта, который должен быть уникальным, имеет два поля - fieldA и fieldB , оба уникальных:

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

Предположим, у меня уже есть запись в базе данных со значениями:

  • fieldA = 'value_a', fieldB = 'value_b'

Теперь, когда я пытаюсь отправить из формы еще один со значениями (fieldA = 'value_a', fieldB = 'value_c'), Symfony2 генерирует запрос для проверки уникальности:

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

И проверка проходит, потому что результатом является пустой набор, но Я ожидаю, что это не удастся, потому что fieldA не будет уникальным в этом случае . (Вставка SQL завершается неудачно с ошибкой повторяющейся записи в 'value_a'.)

Документация Symfony2 UniqueEntity гласит :

Эта обязательная опция - поле (или список полей), в котором этот объект должен быть уникальным. Например, вы можете указать, что поля электронной почты и имя в приведенном выше примере пользователя должны быть уникальными.

Я думаю, это подтверждает мои ожидания.

В источнике UniqueEntityValidator (строка 94) я обнаружил , что валидатор принимает поля в виде массива и использует метод магического поиска "findBy" для проверки уникальности. Этот метод использует отношение «И» между параметрами в запросе, что вызывает проблему.

Возможно ли как-то использовать это ограничение проверки для моей проблемы, или мне нужно проверить его по-другому?

Ответы [ 2 ]

16 голосов
/ 23 июля 2014

Должно быть:

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

Делая

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

он проверит, нет ли строк с одинаковыми обоими полями.

Предположим, у вас уже есть запись в базе данных со значениями:

fieldA = 'value_a', fieldB = 'value_b'

Теперь, когда вы пытаетесь отправить еще один со значениями (fieldA = 'value_a', fieldB = 'value_c') из формы, Symfony2 генерирует запрос для проверки уникальности:

ВЫБРАТЬ ... ОТ ... ГДЕ fieldA =? И поле B =? ('value_a', 'value_c')

и это пройдет, потому что оно не соответствует строке с

fieldA = 'value_a', fieldB = 'value_b'

только когда вы отправляете из формы еще одно со значениями (fieldA = 'value_a', fieldB = 'value_b'), проверка не пройдет.

Вот как это должно работать и как это объясняется в документации: http://symfony.com/doc/current/reference/constraints/UniqueEntity.html#fields

10 голосов
/ 13 декабря 2011

А как же:

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

?

...