2011-12-13 29 views
5

Tôi đang cố xác thực tính duy nhất của một thực thể được gửi từ biểu mẫu bằng cách sử dụng Ràng buộc xác thực UniqueEntity trên nhiều trường.Symfony2 UniqueEntity nhiều trường: xác thực dương tính giả?

Mã của thực thể đó phải là duy nhất có hai lĩnh vực - fieldAfieldB, cả độc đáo:

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

Giả sử tôi đã có một kỷ lục trong cơ sở dữ liệu với các giá trị:

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

Bây giờ khi tôi cố gắng để gửi nhau với các giá trị (fieldA = 'value_a', fieldB = 'value_c') từ một hình thức, Symfony2 tạo ra một truy vấn để kiểm tra tính độc đáo:

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

Và xác nhận đi, bởi vì kết quả là một tập rỗng, nhưng Tôi hy vọng nó sẽ thất bại, bởi vì fieldA sẽ không là duy nhất trong trường hợp này. (The chèn SQL thất bại với một lỗi nhập trùng lặp trên 'value_a'.)

Symfony2's UniqueEntity documentation says:

tùy chọn cần thiết Đây là lĩnh vực (hoặc danh sách các lĩnh vực) mà tổ chức này phải là duy nhất. Ví dụ: bạn có thể chỉ định rằng cả trường email và tên trong ví dụ Người dùng ở trên phải là duy nhất.

Tôi nghĩ nó xác nhận sự mong đợi của tôi.

Tôi phát hiện ra in the source of UniqueEntityValidator (line 94), trình xác thực sẽ lấy trường dưới dạng mảng và sử dụng phương pháp tìm kiếm ma thuật "findBy" để kiểm tra tính duy nhất. Phương thức này sử dụng mối quan hệ 'AND' giữa các tham số trong truy vấn, điều này gây ra vấn đề.

Có thể sử dụng ràng buộc xác thực này cho vấn đề của tôi bằng cách nào đó hoặc tôi phải xác thực nó theo cách khác?

Trả lời

8

gì về:

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

?

+0

Cảm ơn bạn, nó hiện công việc! Vấn đề duy nhất, là mỗi khẳng định có một truy vấn khác, nhưng tôi nghĩ rằng tôi có thể sống với nó. – csabavegso

+1

Nếu không, bạn luôn có giải pháp để viết cho mình Validator, với cảm hứng của UniqueEntity Validator – webda2l

13

Nó nên là:

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

Bằng cách

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

nó sẽ kiểm tra nếu không có bất kỳ hàng với cả hai lĩnh vực giống nhau.

Vì vậy, giả sử bạn đã có một kỷ lục trong cơ sở dữ liệu với các giá trị:

fieldA = 'value_a', fieldB = 'value_b' 

Bây giờ khi bạn cố gắng để gửi nhau với các giá trị (fieldA = 'value_a', fieldB = 'value_c') từ một hình thức , Symfony2 tạo truy vấn để kiểm tra tính duy nhất:

CHỌN ... TỪ ... WHERE fieldA =?VÀ fieldB =? ('Value_a', 'value_c')

và điều này sẽ vượt qua, vì nó không phù hợp với một hàng với

fieldA = 'value_a', fieldB = 'value_b' 

chỉ khi yo nộp nhau với các giá trị (fieldA = 'value_a', fieldB = 'value_b') từ một biểu mẫu, xác thực sẽ không vượt qua.

Đây là cách nó nên làm việc và làm thế nào nó được giải thích trong tài liệu hướng dẫn: http://symfony.com/doc/current/reference/constraints/UniqueEntity.html#fields

Các vấn đề liên quan