2013-03-19 57 views
2

这些是我在SF2上的第一步。我想在包含其他实体的实体上设置多步表单。Symfony2将多步形式合并为一个结果

我有一个表单类型(缩短)

class ApplicationFormType extends AbstractType 
{ 
    protected $_step = 1; 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     if ($this->_step == 1) { 
      $builder 
       ->add('patient', new Type\PersonType()) 
       ->add('insurance', 'entity', array(
        'class' => 'Acme\MainBundle\Entity\Insurance', 
       )); 
     } elseif ($this->_step == 2) { 
      $nurse = new Type\PersonType(); 
      $nurse->requireBareData(); 
      $builder 
       ->add('nurse', $nurse) 
       ->add('nurse_type', 'entity', array(
        'class' => 'Acme\MainBundle\Entity\NurseType', 
        'expanded' => true, 
        'multiple' => false, 
       )) 
       ->add('nursing_support', 'checkbox', array(
        'required' => false, 
       )); 
     } 
    } 

    public function setStep($step) 
    { 
     $this->_step = $step; 
    } 

我的控制器看起来像

public function assistAction() { 
    $request = $this->getRequest(); 

    $step = $this->getSession()->get('assist_step', 1); 
    if ($request->getMethod() != 'POST') { 
     $step = 1; 
     $this->getSession()->set('assist_data', NULL); 
    } 
    $this->getSession()->set('assist_step', $step); 
    $application = new Application(); 
    $type = new ApplicationFormType(); 
    $type->setStep($step); 

    $form = $this->createForm($type, $application, array(
     'validation_groups' => array($step == 1 ? 'FormStepOne' : 'FormStepTwo'), 
    )); 
    if ($request->getMethod() == 'POST') { 
     $form->bindRequest($request); 
     if ($form->isValid()) { 
      if ($step == 1) { 

       $data = $form->getData(); 
       $this->getSession()->set('assist_data', serialize($data)); 
       $this->getSession()->set('assist_step', ++$step); 
       $type = new ApplicationFormType(); 
       $type->setStep($step); 
       $form = $this->createForm($type, $application, array(
        'validation_groups' => array('FormStepTwo'), 
       )); 

      } else { 

       $step_1 = unserialize($this->getSession()->get('assist_data', '')); 
       $data = $form->getData(); 
=>    $data->setPatient($step_1->getPatient()); 
=>    $data->setInsurance($step_1->getInsurance()); 
       $this->getSession()->set('assist_data', NULL); 
       $this->getSession()->set('assist_step', 1); 

      } 
     } 
    } 

    return $this->render('Acme:Default:onlineassist.html.twig', array(
     'form' => $form->createView(), 
     'step' => $step, 
    )); 
} 

我的问题是,如果我不得不“复制”第一种形式一步的性能seperately,像:

$data->setPatient($step_1->getPatient()); 
$data->setInsurance($step_1->getInsurance()); 

或I可以合并从会话中的序列化的数据和从第二形式数据STE P + 还是有一个完全不同的方法?

+0

多步表单的最终目的是什么?您希望在整个过程中保留提交的数据(如果有效),并且一旦客户检查数据,然后将其注入数据库中,对吗? – 2013-03-20 05:50:30

+0

@ThomasPotaire:不完全。客户端不检查数据。正如你所看到的(在FormType中)第二步提供了另一个实体字段由用户填充。 (并且会有第三步。)当用户完成所有步骤时(顺便说一句:第二个步骤很快就会选择),包含所有相关实体的Application实体应该被保存到DB中。 – rabudde 2013-03-20 06:17:19

回答

0

好了,发现比seperately设定步前场,像

$pre_step = unserialize($this->getSession()->get('assist_data', '')); 
$data->setPatient($pre_step->getPatient()); 
$data->setInsurance($pre_step->getInsurance()); 
$data->setInsuranceNumber($pre_step->getInsuranceNumber()); 
$data->setInsuranceLevel($pre_step->getInsuranceLevel()); 

,并且没有其他办法就是我已经这样做的远。

1

实体可以根据stackoverflow上的响应序列化并放入会话中。

如果每个表单都是不同的类型,我建议您将多种类型的类型分开。

这里是我想象它:

public function submitAction($step = 1) 
{ 
    switch ($step) { 
     case 1: 
      $entity = new EntityOne(); 
      $form = $this->createForm(new EntityOneType(), $entity); 
      $template = "template_one.html.twig"; 
      $redirect = $urlToStepTwo; // which redirects to this controller action with $step = 2 
      break; 
     case 2: 
      $entity = new EntityTwo(); 
      $form = $this->createForm(new EntityTwoType(), $entity); 
      $template = "template_two.html.twig"; 
      $redirect = $urlToStepThree; // which redirects to this controller action with $step = 3 
      break; 
     case 3: 
      $entity = new EntityThird(); 
      $form = $this->createForm(new EntityThreeType(), $entity); 
      $template = "template_three.html.twig"; 
      $redirect = $urlToConfirmPage; // which redirects to another controller action that unserialize all entities and save them in the DB 
      break; 
     default: 
      throw $this->createNotFoundException(); 
      break; 
    } 

    $request = $this->get('request'); 
    $session = $this->get('session'); 

    if ($request->isMethod('post') === true) { 

     $form->bind($request); 

     if ($form->isValid() === true) { 
      $session->set('entity_'. $step, serialize($entity)); 

      return $this->redirect($redirect); 
     } 
    } 

    $params = array(
     'form' => $form->createView(), 
     'entity' => $entity 
    ); 

    return $this->render($template, $params); 
} 
+0

您的解决方案当然适用于单独的实体。但我在这三个步骤中有两个使用了一个大实体。 'ApplicationFormType'表示一个'Application'实体。 (顺便说一句:你的代码不符合SF2.2,即'bindRequest'与'bind'和'getMethod()'与'isMethod('post')') – rabudde 2013-03-21 09:56:07

+0

你可以创建两个表单类型来表示一组数据'应用程序'并将它们融合在一起(谢绝任何弃用的通话)。 – 2013-03-21 14:57:07

+0

这正是我正在做的(看看我的帖子)。这就是我的问题。如何合并这两个步骤。可以用PHP中的一条语句来完成,还是让我手动设置第二步中第一步的每个属性? – rabudde 2013-03-21 18:41:38