2015-01-02 4 views
2

"프로젝트"와 관련된 "역할"이 있습니다. 역할 이름이 중복 되어도 상관 없지만 각 프로젝트에 대해 역할 이름을 복제 할 수 없도록하고 싶습니다.Symfony2/Doctrine ManyToOne 엔터티의 UniqueEntity가 무시되었습니다.

<?php 
// src/AppBundle/Entity/Role.php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 

/** 
* @ORM\Entity(repositoryClass="AppBundle\Entity\RoleRepository") 
* @ORM\Table(name="roles") 
* @UniqueEntity(fields={"name","project"}, message="Duplicated role for this project") 
*/ 
class Role 
{ 
/** 
* @ORM\Column(type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
protected $id; 

/** 
* @ORM\Column(type="string", length=100) 
*/ 
protected $name; 

/** 
* @ORM\Column(type="text") 
*/ 
protected $description; 

... 
other fields 
... 

/** 
* @ORM\ManyToOne(targetEntity="Project") 
*/ 
protected $project; 
} 

을 내가 필요 정확히 문서 here에 따르면 :

이 필요한 옵션에 대한 필드 (또는 필드의 목록)이며 여기에

내가 일을해야한다고 생각 것입니다 이 엔티티는 고유해야합니다. 예를 들어 이메일 과 이름 필드를 단일 UniqueEntity 제약 조건에 모두 지정했다면 은 조합 값이 고유 한 경우에만 적용됩니다 (예 : 두 명의 사용자가 에 동일한 이메일을 가질 수 있음). 같은 이름도).

같은 제약 조건은 무시됩니다. 동일한 프로젝트에 대해 동일한 역할 이름을 사용하려고하면 중복 된 역할 이름과 projectID가 저장됩니다.

무엇이 누락 되었습니까?

EDIT : "php app/console doctrine : schema : update --force"로 DB를 업데이트 한 후 SQL을 사용하여 직접 오류를 생성하려고했지만 예외가 발생하지 않았습니다. 이제이 "UniqueEntity"유효성 검사가 DB 수준에서 수행되는지 아니면 Doctrine의 유효성 검사기에서 수행되는지는 알 수 없습니다.

EDIT2 : 하나의 필드 ("이름") 만 사용하려고했는데 유효성 검사가 제대로 작동했습니다 (물론 해당 필드에서만). "name"및 "description"필드에 대한 유효성 검사를 시도했는데 작동합니다! 따라서 기본적으로 유효성을 검사 할 필드가 다른 테이블을 가리키는 ID인지 확인하지 않습니다.

어쨌든, 여기에 컨트롤러 :

/** 
* @Route("/role/create/{projectID}", name="role_create") 
*/ 
public function createRoleAction(Request $request, $projectID) 
{ 
    $prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($projectID); 

    $role = new Role(); 
    $form = $this->createForm(new RoleFormType(), $role); 

    $form->handleRequest($request); 

    if ($form->isValid()) 
     { 
     $em = $this->getDoctrine()->getManager(); 
     $role->setProject($prj); 
     $em->persist($role); 
     $em->flush(); 
     return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $projectID))); 
     } 

return $this->render('Role/createForm.html.twig', array('projectID' => $projectID, 'form' => $form->createView(),)); 
} 

검증이 수행되지 않으며, 기업은 바로 프로젝트에서 "프로젝트"열을 가리키는, DB에 지속되었다. 여기 enter image description here

RoleFormType (관련 분야의 발췌)입니다 :

<?php 
namespace AppBundle\Form\Type; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class RoleFormType extends AbstractType 
{ 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    // add your custom field 
    $builder->add('name', 'text') 
      ->add('description', 'text') 
      ...lots of other fields, but "project" is not present as it's passed automatically from the controller 
      ->add('save', 'submit', array('label' => 'Create')); 

} 

public function getName() 
{ 
    return 'role'; 
} 

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array('data_class' => 'AppBundle\Entity\Role',)); 
} 

} 
+0

Symfony \ Bridge \ Doctrine \ Validator \ Constraints \ UniqueEntity;를 사용하셨습니까? – sjagr

+0

불행하게도 나는 다음과 같이했다 : /. 그것이 ManyToOne 필드에서 작동 할 수 있는지 궁금하네요 (https://stackoverflow.com/questions/20282361/symfony2-uniqueentity-with-many-to-one-field?rq=1) 여기에서 찾을 수 있습니다. –

+0

[주석 사용] (http://symfony.com/doc/current/book/validation.html#configuration) 했습니까? – sjagr

답변

2

문제는 당신이 실제로 고유를 확인하기 위해 엔티티를 검증되지 않습니다이다 여기에 2 개 관련 필드의 스냅 샷입니다 제약 조건 위반. $form->isValid()에 전화 할 때 양식의 데이터 클래스로 전달한 이후 Role 엔터티의 유효성 검사기를 호출합니다. 그러나 이후 project 때까지 설정되지 않으므로 project 필드에 유효성 검사가 발생하지 않습니다.

$em->persist($role);$em->flush();을 호출하면 Doctrine에 데이터베이스에 엔티티를 삽입하도록 지시합니다. 이 두 번의 호출은 이 아니며은 자체적으로 유효성 검사를 수행하므로 이됩니다.대신 양식을 작성하기 전에 프로젝트를 설정

시도가 :

$role = new Role(); 
$role->setProject($prj); 

$form = $this->createForm(new RoleFormType(), $role); 

은 이제 프로젝트는 $form->isValid()는 심포니 검사기 고유성를 확인합니다라고 그렇게 할 때 개체에 설정됩니다.

그래도 작동하지 않으면 project 유형을 hidden 필드 형식으로 양식에 추가하여 전달할 수 있지만 필요하지는 않습니다.

내가 말하고자하는 또 다른 사항은 데이터베이스 자체에 고유 제한 조건을 추가하고 싶다는 것입니다.이 방법을 사용하면 복제본을 삽입해도 데이터베이스가 예외를 다시 발생시키고 허용하지는 않습니다. 당신의 코드에 관계없이.

+0

예, $ form-> isValid()가 트릭을 수행하기 전에 $ role-> setProject ($ prj)를 이동했습니다! 그것은 모든 의미를 갖습니다. 고맙습니다! –

+0

때로는이 코드 전체에서 앞뒤로 갈 방법이 너무 깊어서 해결책이 너무 간단 할 때 문제를 찾는 것이 재미있을 수도 있습니다. –

+0

projectID가 null이 아니라면 매력이 있습니다. 하지만 null 일 경우 유효성 검사가 예상대로 수행되지 않습니다. 단서? –