Уникальные ограничения в Doctrine 2, Symfony 2 - PullRequest
28 голосов
/ 17 декабря 2011

Я хочу создать уникальное ограничение в моей сущности Doctrine 2, чтобы name & test были уникальными столбцами.Значение

  • obj1

    • имя: имя1
    • тест: тест
  • obj2

    • имя: имя2
    • test: test <---- продублировано </li>

Это должно вызвать ошибку в качестве тестадублируется

Я пытался использовать ограничение уникальности (Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity).Попытки

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

и

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

Кажется, что оба эти сообщения вызывают ошибку только тогда, когда у меня ОБА имя и тест дублированы.например.

  • obj1

    • name: name1
    • test: test
  • obj2

    • name: name2
    • test: test

Что такое правильная настройка?Или я мог где-то ошибиться?

Возможно, мне следует включить аннотацию доктрины, такую ​​как:

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

Но это все еще не справится с моей проверкой формы Symfony, я думаю?* ОБНОВЛЕНИЕ

Мой тестовый код:

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

При первом запуске (пустая таблица):

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

Но я получаю ошибкуна уровне базы данных об уникальном ограничении.Так как мне получить рабочий слой валидации, хотя?

Ответы [ 2 ]

50 голосов
/ 17 декабря 2011

Они проверяют поля по отдельности:

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

То есть первое срабатывает при наличии дублированного значения name, а второе - при наличии дубликата test значения.

Если вы хотите, чтобы проверка завершилась неудачно, когда оба name и test содержат одну и ту же комбинацию , используйте следующее:

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

Для того, что вы хотите, первый подход должен работать - если вы не сделали что-то не так в другом месте.Также попытайтесь очистить кэш, чтобы убедиться, что это не его ошибка.

ОБНОВЛЕНИЕ

То, что я предлагал, касалось части проверки на стороне приложения.Если вы генерируете схему базы данных, используя Doctrine, вам нужно будет предоставить аннотации уровня Doctrine для каждого столбца - если вы хотите сделать их уникальными независимо друг от друга, конечно:

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

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

Эти подходы дополняют друг друга - не исключают.@UniqueEntity гарантирует, что дубликат даже не достигнет уровня базы данных, а @Column гарантирует, что если он это сделает, слой базы данных не пропустит его.

49 голосов
/ 28 сентября 2012

В аннотации таблицы вы также можете установить индекс для нескольких столбцов .

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

или в формате YAML:

Namespace\Entity\EntityName:
    type: entity
    table: ecommerce_products
    uniqueConstraints:
        uniqueConstraint:
            columns: [name, email]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...