1

I'm trying to make a multi-step form with CraueFormFlow. The CraueForm need a class to hydrate but I have several entities so I dit a addChildWizard class where all I have my needed entities as properties like this :

    <?php

    namespace VS\CrmBundle\Entity;

    use Doctrine\Common\Collections\ArrayCollection;
    use VS\CrmBundle\Entity\MedicalRecord;
    use VS\CrmBundle\Entity\Person;
    use VS\CrmBundle\Entity\Relationship;
    use Doctrine\ORM\Mapping as ORM;

    /**
     *
     * Class AddChildWizard
     * @package VS\CrmBundle\Entity
     */
    class AddChildWizard
    {
        /**
         * Step 1
         *
         * @var Relationship
         */
        protected $currenUserChildRelationship;

        /**
         * Step 1
         *
         * @var Person
         */
        protected $child;

        /**
         * Step 2
         *
         * @var MedicalRecord
         */
        protected $childsMedicalRecord;

        /**
         * Step 3
         *
         * This is a collection of Relationship entities
         *
         * @var ArrayCollection
         */
        protected $childsFamily;

        public function __construct()
        {
            $this->childsFamily = new ArrayCollection();
        }
+ getters and setters

Then I have my flow class :

<?php

namespace VS\CrmBundle\Form\Wizard\AddChild;

use Craue\FormFlowBundle\Form\FormFlow;
use Craue\FormFlowBundle\Form\FormFlowInterface;


class AddChildFlow extends FormFlow {
    protected function loadStepsConfig()
    {
        return array(
            array(
                'label' => 'ChildData',
                'form_type' => 'VS\CrmBundle\Form\Wizard\AddChild\AddChildStep1'
            ),
            array(
                'label' => 'ChildMedicalRecord',
                'form_type' => 'VS\CrmBundle\Form\Wizard\AddChild\AddChildStep2'
            ),
            array(
                'label' => 'ChildFamily',
                'form_type' => 'VS\CrmBundle\Form\Wizard\AddChild\AddChildStep3'
            ),
            array(
                'label' => 'confirmation',
            ),
        );
    }
}

With one form for each step. For example step 1 is :

<?php

namespace VS\CrmBundle\Form\Wizard\AddChild;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use VS\CrmBundle\Entity\Person;
use VS\CrmBundle\Entity\Relationship;
use VS\CrmBundle\Form\PersonChildType;
use VS\CrmBundle\Form\RelationshipFromCurrentUserType;

class AddChildStep1 extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('currenUserChildRelationship', RelationshipFromCurrentUserType::class, array(
                'data_class' => Relationship::class
            ))
            ->add('child', PersonChildType::class, array(
                'data_class' => Person::class
            ));
    }

    public function getBlockPrefix()
    {
        return 'AddChildStep1';
    }
}

And the action is :

 public function addChildAction()
    {

        // Our form data class
        $formData = new AddChildWizard();

        // We call service (craue form flow)
        $flow = $this->get('vs_crm.form.flow.add_child');
        $flow->bind($formData);

        $form = $flow->createForm();



        if($flow->isValid($form))
        {
            $flow->saveCurrentStepData($form);

            if($flow->nextStep())
            {
                $form = $flow->createForm();
            }
            else
            {
                $child = $formData->getChild();
                $curentUserRel = $formData->getCurrenUserChildRelationship();
                $currentUser = $this->get('security.token_storage')->getToken()->getUser();
                $medicalRecord = $formData->getChildsMedicalRecord();
                $family = $formData->getChildsFamily();

                $curentUserRel->setSourceId($child);
                $curentUserRel->setDestinationId($currentUser);
                $medicalRecord->setPerson($child);

                foreach($family as $member)
                {
                    $member->setSourceId($child);
                }

                //return new JsonResponse(array($formData->getId()));

                // flow finished

                $em = $this->getDoctrine()->getManager();
                $em->persist($formData);
                $em->flush();

                $flow->reset();

                $this->addFlash('success', 'Your child has been saved.');
                return $this->redirectToRoute('vs_crm_parent_dashboard');

            }
        }

        return $this->render('VSCrmBundle:Parent:add-child.html.twig', array(
            'form' => $form->createView(),
            'flow' => $flow
        ));
    }

This works perfectly, but at the end I have this error :

Class "VS\CrmBundle\Entity\AddChildWizard" is not a valid entity or mapped super class.

So doctrine wants an entity with the @Entity annotation and a Identifier and our friend Doctrine want to save the identifier in the Database ....

Is there an other way to do this stuff without saving the id in the database or I should listen to our friend Doctrine ?

Grechka Vassili
  • 853
  • 4
  • 15
  • 32

1 Answers1

1

Ok, If it can help someone...

At the end I had $em->persist($formData);and this is why Doctrine wanted my class addChildWizard ($formData = new AddChildWizard();) to be an entity. What I did is :

 $em->persist($child);
 $em->persist($curentUserRel);
 $em->persist($medicalRecord);

 foreach($family as $familyMember)
 {
     $em->persist($familyMember);
 }

And now this multi-step form works perfectly !

Grechka Vassili
  • 853
  • 4
  • 15
  • 32