Symfony2 UniqueEntity多个字段:误报验证?

csa*_*gso 6 validation orm symfony doctrine-orm

我正在尝试通过在多个字段上使用UniqueEntity Validation Constraint来验证从表单提交的实体的唯一性.

应该唯一的实体代码有两个字段 - fieldAfieldB,两者都是唯一的:

/**
 * @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;
}
Run Code Online (Sandbox Code Playgroud)

假设我已经在数据库中有一个值为的记录:

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

现在,当我尝试从表单中提交另一个值(fieldA ='value_a',fieldB ='value_c')时,Symfony2会生成一个查询以检查唯一性:

SELECT ... FROM ... WHERE fieldA = ? AND fieldB = ? ('value_a', 'value_c')
Run Code Online (Sandbox Code Playgroud)

并且验证通过,因为结果是空集,但我希望它失败,因为在这种情况下fieldA将不是唯一的.(SQL插入失败,并在'value_a'上出现重复的条目错误.)

Symfony2的UniqueEntity文档说:

此必需选项是此实体应该唯一的字段(或字段列表).例如,您可以指定上述用户示例中的电子邮件和名称字段都应该是唯一的.

我认为这证实了我的期望.

在UniqueEntityValidator(第94行)的源代码中发现,验证器将字段作为数组,并使用"findBy"魔术查找器方法来检查唯一性.此方法使用查询中的参数之间的"AND"关系,这会导致问题.

是否有可能以某种方式对我的问题使用此验证约束,或者我必须以另一种方式验证它?

Jim*_*oot 16

它应该是:

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

通过做

 * @DoctrineAssert\UniqueEntity(fields = {"fieldA", "fieldB"})
Run Code Online (Sandbox Code Playgroud)

它将检查两个字段是否存在相同的行.

因此,假设您已在数据库中拥有值的记录:

fieldA = 'value_a', fieldB = 'value_b'
Run Code Online (Sandbox Code Playgroud)

现在,当您尝试从表单提交另一个值(fieldA ='value_a',fieldB ='value_c')时,Symfony2会生成一个查询以检查唯一性:

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

这会传递,因为它与行不匹配

fieldA = 'value_a', fieldB = 'value_b'
Run Code Online (Sandbox Code Playgroud)

只有当您从表单中提交另一个值(fieldA ='value_a',fieldB ='value_b')时,验证才会通过.

这是它应该工作的方式以及如何在文档中解释它:http: //symfony.com/doc/current/reference/constraints/UniqueEntity.html#fields


web*_*a2l 10

关于什么 :

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