[英]Symfony2 Doctrine2 UniqueEntity on ManyToOne field is ignored
我在Project
和Application
之間具有OneToMany
關系,並且我想確保兩個Application
不能在Project
具有相同的名稱。
我試圖像應該配置的那樣配置實體,表單類型和控制器,但是對於重復輸入,我遇到了完整性沖突,因此我認為驗證過程被忽略了。
有人可以告訴我我想念什么嗎?
我的Application
實體是這樣的:
namespace App\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use JsonSerializable;
/**
* @ORM\Entity
* @ORM\Table(name="application", uniqueConstraints={@ORM\UniqueConstraint(name="IDX_Unique", columns={"name", "project_id"})})
* @UniqueEntity(
* fields={"name", "project"},
* message="Name already used in this project.",
* groups="application"
* )
*/
class Application implements JsonSerializable {
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string")
* @Assert\NotBlank(
* message = "Name cannot be empty."
* )
* @Assert\Length(
* min = "3",
* max = "50",
* minMessage = "Name is too short. It should have {{ limit }} characters or more.",
* maxMessage = "Name is too long. It should have {{ limit }} characters or less."
* )
*/
protected $name;
// other properties ...
/**
* @ORM\ManyToOne(targetEntity="Project", inversedBy="applications")
* @ORM\JoinColumn(name="project_id", referencedColumnName="id")
*/
protected $project;
// constructor, methods, getters, setters
}
我的ApplicationType
類如下所示:
namespace App\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ApplicationType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('name', 'text', array(
'icon' => 'pencil'
));
$builder->add('description', 'textarea', array(
'required' => false,
'icon' => 'info'
));
$builder->add('url', 'url', array(
'required' => false,
'icon' => 'link'
));
}
public function getName() {
return 'application';
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'App\MainBundle\Entity\Application',
'validation_group' => array('application'),
'cascade_validation' => true
));
}
}
在我的Controller
,操作如下所示:
/**
* @Route("/project/{id}/application/add",
* name="app_add_application_ajax",
* requirements={"_method" = "post"},
* options={"expose" = true }
* )
* @Secure(roles="ROLE_SUPER_ADMIN")
* @ParamConverter("project", class="AppMainBundle:Project")
*/
public function addApplicationAction(Project $project, Request $request) {
$ajaxResponse = array();
$em = $this->getDoctrine()->getManager();
if ($request->getMethod() == 'POST' && $request->isXmlHttpRequest()) {
$formApp = new Application();
$formApp->setProject($project);
$form = $this->createForm(new ApplicationType(), $formApp);
$form->handleRequest($request);
if ($form->isValid()) {
$application = $form->getData();
$em->persist($application);
$em->flush();
// build ajax response ...
} else {
$ajaxResponse['error'] = $this->getErrorsAsString();
}
}
$response = new Response(json_encode($ajaxResponse));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
您的問題是您在表單類型中配置了一個validation_group
選項,而Symfony使用的選項是validation_groups
。 您不會收到有關未知選項的錯誤,因為您是在表單類型的默認選項中進行設置的,因此您將選項標記為已定義(但它是單獨的)。
因此,驗證器與默認組一起運行,它將驗證不同的約束(對name屬性長度的約束位於默認組中)。
請注意,您還有第二個問題,一旦運行約束,該問題就會出現。
您的驗證約束與您擁有的數據庫約束不匹配。 您要求驗證者具有唯一的名稱和唯一的項目,而不是唯一的元組(名稱,項目)。 因此,您會拒絕太多的事情(名稱將在全球范圍內(而不是在每個項目中)被驗證為唯一)。 這是因為您使用2個單獨的UniqueEntity約束,而不是要求多個字段的元組唯一的約束。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.