在表单验证之前设置实体参数

时间:2017-08-27 00:42:46

标签: php symfony symfony-forms

[设置]

  • Symfony 3
  • BoxEntity:[id,name]
  • CandyEntity:[id,name]

[问题]

目前,在创建新糖果时,我必须选择一个方框作为父实体 问题是,我希望这种选择是自动化的 该框已在数据库中注册,并且会话保持当前框参数以便轻松找回它 但是,一旦数据发布,我无法弄清楚如何将它应用于糖果实体。

[FILES]

的appbundle /控制器/ CandyController.php

public function newAction(Request $request) {
    $$candy= new Candy();
    $form = $this->createForm('AppBundle\Form\CandyType', $conference);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($candy);
        $em->flush();

        return $this->redirectToRoute('candy_show', array('id' => $candy->getId()));
    }

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

的appbundle /形式/ CandyType.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('nom')
            ->add('box'); //Remove from form, and set manually
}

我做了read this page,但无法弄清楚如何正确地做到这一点 如果有人能够给我一个完整的例子来解决我的问题,那将非常感激。

1 个答案:

答案 0 :(得分:1)

您有多种选择可以执行您想要的操作。您可以在表单提交后设置值:

public function newAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();

    $candy = new Candy();
    $box = $em->find('AppBundle\Entity\Box', $this->get('session')->get('boxId'));

    $form = $this->createForm('AppBundle\Form\CandyType', $candy);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        // add the box entity to the candy
        $candy->setBox($box);

        $em->persist($candy);
        $em->flush();

        return $this->redirectToRoute('candy_show', array('id' => $candy->getId()));
    }

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

您可以在将Candy实体传递给createForm()来之前将其设置在该实体上,尽管在执行handleRequest()表单后它可能不会留在实体上:

    $em = $this->getDoctrine()->getManager();

    $candy = new Candy();
    $box = $em->find('AppBundle\Entity\Box', $this->get('session')->get('boxId'));

    $candy->setBox($box);

    $form = $this->createForm('AppBundle\Form\CandyType', $candy);
    $form->handleRequest($request);

您可以在表单事件中以您尝试的方式执行此操作。您想要做的是将实体管理器和会话注入表单并将表单视为服务:

public function CandyType extends AbstractType
{
    private $em;
    private $session;

    public function __construct(EntityManager $em, SessionInterface $session)
    {
        $this->session = $session;
        $this->em      = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ... build the form

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) {
                $form = $event->getForm();

                $candy = $event->getData();
                $box = $this->em->find('AppBundle\Entity\Box', $this->session->get('boxId');

                $candy->setBox($box);
            }
        );
    }
}

您可能需要在POST_SET_DATAPOST_SUBMIT事件中执行此操作,但我不确定。我还在Controller中使用了$this->get('session'),但根据您的Symfony版本(> 3.3),您可以将其作为服务注入控制器。

无论哪种方式,主要概念是使用Doctrine使用会话中存储的box id从会话本身获取Box实体,然后在Candy实体上设置它。您甚至可以使用hidden字段来获得相同的结果。正如我之前所说,有很多方法可以解决你的问题。