Symfony表单 - 删除嵌入表单中的可选一对一关系

时间:2015-12-09 19:48:48

标签: forms symfony

我正在尝试使用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;

0 个答案:

没有答案