我正在尝试使用Symfony Forms来编辑与另一个可选实体具有一对一关系的现有实体。我想这样做,如果它没有收到关联实体的任何内容,它将删除该实体。
以下是我编写的代码的要点:
class AType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('BType', new BType(), ['required' => false]);
}
}
A实体与B的关联:
class A
{
/**
* @ORM\OneToOne(
* targetEntity="B",
* mappedBy="a",
* cascade={"persist", "remove"},
* orphanRemoval=true
* )
* @Assert\Valid()
*/
private $b;
....
当我尝试将表单与数据绑定时,即使没有为B提交任何内容,它也会使B的字段为空白的验证错误,因为存在与A关联的现有B实体。
我也看过FormEvents,但我也找不到解决这个问题的方法 - 我尝试添加到AType的buildForm的例子:
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
$a = $event->getData();
if($a->getType() != 'Package') {
$a->setB(null);
}
});
即使使用这些附加代码,关于B的错误仍然出现。
更新
我想我已经接近了,但是虽然我可以告诉它正确地进入新代码,但B实体仍然没有最终被删除,我认为因为尽管$a->setB(null)
,{{1在控制器中,$a = $form->getData();
仍然返回数据(即在AType的POST_SUBMIT中编辑实体似乎只在本地更改该数据?)
新守则:
$a->getB();
我真的很茫然,因为虽然$builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
$data = $event->getData();
if(!isset($data['B'])) {
$event->getForm()->remove('B');
}
});
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
$a = $event->getData();
if(!$event->getForm()->has('B') && $a->getB()) {
$a->setB(null);
}
});
没有延续到控制器,但如果我创建一个属性$ a-> test并将其设置在同一位置,那确实会延续到控制器。
更新2
根据评论,我正在添加来自实体B和控制器的一些代码:
$a->setB(null)
至于控制器,它变得更加复杂,因为我实际上正处理一个2深度关系:C hasMany A hasOne B.它也没有使用表单输入,而是格式化json。我正在使用http://jmsyst.com/bundles/JMSSerializerBundle/master/installation将输出序列化为json,以及一个帮助函数来序列化任何错误消息。
class B
{
/**
* @var \A
*
* @ORM\GeneratedValue(strategy="NONE")
* @ORM\OneToOne(targetEntity="A", inversedBy="b", cascade={"persist"})
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="a_id", referencedColumnName="id")
* })
*/
private $a;
A与C的关系
//Where $c is either a new C entity or an existing C entity to be edited
private function handleForm($c)
{
$json = $this->getJsonFromRequest();
if (false === $json) {
throw new \Exception('Invalid JSON');
}
$form = $this->createForm(new CType(), $c);
$em = $this->getDoctrine()->getEntityManager();
if($form->bind(json_decode($json, true)) && $form->isValid()) {
$c = $form->getData();
...
$em->persist($c);
$em->flush();
$response = new Response($this->getSerializer()->serialize($c, 'json'));
$response->headers->set('Content-Type', 'application/json');
return $response;
} else {
$response = array('code' => 'invalid', 'details' => $this->getErrorMessages($form));
return new JsonResponse($response, 400);
}
}
class C
{
/**
* @ORM\OneToMany(targetEntity="A", mappedBy="c", cascade={"persist", "remove"}, indexBy="id")
* @Assert\Valid()
* @Serializer\Expose
*/
protected $a;
和CType
/**
* @var \C
*
* @ORM\ManyToOne(targetEntity="C", inversedBy="a")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="c_id", referencedColumnName="id")
* })
* @Assert\NotBlank
*/
private $c;