Manipulação de um formulário complexo Symfony2 com relação de entidades múltiplas

Eu tenho um formulário (ainda não terminado e falta muitos campos) que é tratado como um assistente com etapas, nos quais os campos de várias entidades são tratados. Este é o próprio formulário:

public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('tipo_tramite', 'entity', array( 'class' => 'ComunBundle:TipoTramite', 'property' => 'nombre', 'required' => TRUE, 'label' => "Tipo de Trámite", 'query_builder' => function (EntityRepository $er) { return $er->createQueryBuilder('q') ->where('q.activo = :valorActivo') ->setParameter('valorActivo', TRUE); } )) ->add('oficina_regional', 'entity', array( 'class' => 'ComunBundle:OficinaRegional', 'property' => 'nombre', 'required' => TRUE, 'label' => "Oficina Regional", 'query_builder' => function (EntityRepository $er) { return $er->createQueryBuilder('q') ->where('q.activo = :valorActivo') ->setParameter('valorActivo', TRUE); } )) ->add('procedencia_producto', 'entity', array( 'class' => 'ComunBundle:ProcedenciaProducto', 'property' => 'nombre', 'required' => TRUE, 'label' => "Procedencia del Producto" )) ->add('finalidad_producto', 'entity', array( 'class' => 'ComunBundle:FinalidadProducto', 'property' => 'nombre', 'required' => TRUE, 'label' => "Finalidad del Producto" )) ->add('condicion_producto', 'entity', array( 'class' => 'ComunBundle:CondicionProducto', 'property' => 'nombre', 'required' => TRUE, 'label' => "Condición del Producto" )) ->add('lote', 'integer', array( 'required' => TRUE, 'label' => "Tamaño del Lote" )) ->add('observaciones', 'text', array( 'required' => FALSE, 'label' => "Observaciones" )); } 

Eu tenho uma pergunta sobre como lidar com o parâmetro data_class neste caso, então eu não tenho que fazer magia no controlador. Quando digo magia, entendo o seguinte:

 public function empresaAction() { $entity = new Empresa(); $form = $this->createForm(new EmpresaFormType(), $entity); return array( 'entity' => $entity, 'form' => $form->createView() ); } public function guardarEmpresaAction(Request $request) { $em = $this->getDoctrine()->getManager(); /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */ $userManager = $this->container->get('fos_user.user_manager'); /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */ $dispatcher = $this->container->get('event_dispatcher'); /** @var $mailer FOS\UserBundle\Mailer\MailerInterface */ $mailer = $this->container->get('fos_user.mailer'); $request_empresa = $request->get('empresa'); $request_sucursal = $request->get('sucursal'); $request_chkRif = $request->get('chkRif'); $request_estado = $request_empresa[ 'estado' ]; $request_municipio = $request->get('municipio'); $request_ciudad = $request->get('ciudad'); $request_parroquia = $request->get('parroquia'); $user = $userManager->createUser(); $event = new GetResponseUserEvent($user, $request); $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event); if (null !== $event->getResponse()) { return $event->getResponse(); } $entity = new Empresa(); $form = $this->createForm(new EmpresaFormType(), $entity); $form->handleRequest($request); $success = $url = $errors = ""; if ($form->isValid()) { if ($request_sucursal != NULL || $request_sucursal != "") { $padreEntity = $em->getRepository('UsuarioBundle:Empresa')->findOneBy(array( "padre" => $request_sucursal )); if (!$padreEntity) { $padreEntity = $em->getRepository('UsuarioBundle:Empresa')->findOneBy(array( "id" => $request_sucursal )); } if ($request_chkRif != NULL || $request_chkRif != "") { $rifUsuario = $request_empresa[ 'tipo_identificacion' ] . $request_empresa[ 'rif' ]; } else { $originalRif = $padreEntity->getRif(); $sliceRif = substr($originalRif, 10, 1); $rifUsuario = $originalRif . ($sliceRif === false ? 1 : $sliceRif + 1); } $entity->setPadre($padreEntity); } else { $rifUsuario = $request_empresa[ 'tipo_identificacion' ] . $request_empresa[ 'rif' ]; } $user->setUsername($rifUsuario); $user->setRepresentativeName($request_empresa[ 'razon_social' ]); $user->setEmail($request_empresa[ 'usuario' ][ 'email' ]); $user->setPlainPassword($request_empresa[ 'usuario' ][ 'plainPassword' ][ 'first' ]); $pais = $em->getRepository('ComunBundle:Pais')->findOneBy(array( "id" => 23 )); $user->setPais($pais); $estado_id = $request_estado ? $request_estado : 0; $estado = $em->getRepository('ComunBundle:Estado')->findOneBy(array( "id" => $estado_id )); $user->setEstado($estado); $municipio_id = $request_municipio ? $request_municipio : 0; $municipio = $em->getRepository('ComunBundle:Municipio')->findOneBy(array( "id" => $municipio_id )); $user->setMunicipio($municipio); $ciudad_id = $request_ciudad ? $request_ciudad : 0; $ciudad = $em->getRepository('ComunBundle:Ciudad')->findOneBy(array( "id" => $ciudad_id )); $user->setCiudad($ciudad); $parroquia_id = $request_parroquia ? $request_parroquia : 0; $parroquia = $em->getRepository('ComunBundle:Parroquia')->findOneBy(array( "id" => $parroquia_id )); $user->setParroquia($parroquia); ... } else { $errors = $this->getFormErrors($form); $success = FALSE; } return new JsonResponse(array( 'success' => $success, 'errors' => $errors, 'redirect_to' => $url )); } 

Uma vez que o ‘data_class on EmpresaFormType is set to UsuarioBundle \ Entity \ Empresa`, eu preciso lidar com qualquer parâmetro extra como o exemplo acima mostra com getter / setter e isso é muito trabalho para formas complexas / grandes.

Na forma de amostra, os campos tipo_tramite persistirão na class ComunBundle\Entity\Producto mas o campo oficina_regional persistirá na class ComunBundle\Entity\SolicitudUsuario e, portanto, com outros que não são colocados até aqui, mas estão na forma, em O total deve persistir como 3 ou 4 entidades, incluindo relações em muitos casos, como você lida com isso?

Eu sei que há CraueFormFlowBundle que talvez cubra esse processo / stream, mas não tem certeza se é a solução a seguir.

Algum conselho?

Apenas trabalhei com vários passos alguns dias atrás. Eu acho que você precisa de formulários embutidos aqui. De qualquer forma, pode sugerir-lhe outro pacote agradável para o assistente de criação: SyliusFlowBundle . IMO é mais flexível e mais fácil de entender do que o CraueFormFlowBundle.

BTW por que você deseja armazenar tudo de uma forma? Nós usamos um formulário para cada etapa, e eu gostei dessa abordagem.