2012-03-15 2 views
19

내가 FormBuilder 내부의 부모 CollectionType 주어진 포함 된 폼의 개체에 액세스하려고 해요 :심포니 양식 - 액세스 엔티티 A CollectionType의 자식 항목 유형 내부

ParentType

Class ParentType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('children', CollectionType::class, array(
      'entry_type' => ChildType::class 
     ); 
    } 
} 

ChildType

class ChildType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $child = $builder->getData(); // this returns null 
    } 

    public function getDefaultOptions(array $options) 
    { 
     return array(
      'data_class' => 'Vendor\Bundle\Entity\Child', 
     ); 
    } 
} 

정상적인 형식이면 $child이 null로 반환됩니다. ChildType 내부의 Child 엔티티에 어떻게 액세스합니까?

답변

38

답변은 이벤트 청취자을 사용하여 PRE_SET_DATA 이벤트를 수신 대기합니다.

폼과 바인딩 된 데이터가 모두 포함 된 FormEvent 클래스가 클로저를 전달합니다.

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->addEventListener(FormEvents::PRE_SET_DATA, 
     function (FormEvent $event) use ($builder) 
     { 
      $form = $event->getForm(); 
      $child = $event->getData(); 

      if ($child instanceof Child) { 

       // Do what ever you like with $child entity data 

      } 
     } 
    ); 
} 
+1

는 명백한 한때를 요청하려면 estion, 양식의 데이터에 사용되는 상위 엔티티에 바가 있습니까? 상위 양식 유형의 데이터에서 막대 모음을 var_dumping하여 확인할 수 있습니까? – user1207727

+0

감사합니다. 이것은 완벽하게 작동했고 간과 된 문서의 일부로 나를 인도했습니다. [양식 이벤트를 사용하여 양식을 동적으로 생성하는 방법] (http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html) – Nick

+0

Ah , 당신은 내가 그것을 삭제하기 전에 내 의견을 잡았습니다 - 나는 게으름으로 formfactory 귀하의 답변의 일부를 제외하고, 빌더 자체로 계속하려고 노력. 그런 다음 귀하의 솔루션을 축 어적으로 사용하기로 결정했으며 효과가있었습니다. 혼란스럽게 생각합니다! – Nick

2

이것은 user1207727을 기반으로 한보다 자세한 해결책입니다.

부모 유형

class FrontentStatsInputFormType extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('records', CollectionType::class, array(
       'entry_type' => FrontendStatsRecordType::class, 
       'allow_add' => false, 
       'allow_delete' => false, 
       'label' => null, 
      )) 
     ; 
    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => null 
     )); 
    } 
} 

하위 유형

class FrontendStatsRecordType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->addEventListener(FormEvents::PRE_SET_DATA, 
      function (FormEvent $event) use ($builder) 
      { 
       $form = $event->getForm(); 
       $child = $event->getData(); 

       if ($child instanceof StatsRecord) { 

        // Do what ever you like with $child entity data 
        // $child->getSomeValue(); 

        $form->add('value', TextType::class); 
       } 
      } 
     ); 

    } 

    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'AppBundle\Entity\StatsRecord', 
     )); 
    } 

} 

컨트롤러의 양식을 작성

public function indexAction(Request $request, InputForm $inputForm) { 

    $data = array(); 

    foreach ($inputForm->getStatsTemplates() as $template) { 
     $statsRecord = new StatsRecord(); 
     $data['records'][] = $statsRecord; 
    } 


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


    if ($form->isSubmitted() && $form->isValid()) { 

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

     // Get entries and persist them in the database 
     $records = $form->get('records')->getData(); 
     foreach ($records as $record) { 
      $em->persist($record); 
     } 

     $em->flush(); 

     return $this->redirectToRoute('frontend_index'); 
    } 

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