2014-04-27 4 views
2

내 문제는 여기에 있습니다. 기본 데이터를 기반으로 폼에 필드를 추가해야하지만 필드에 데이터 변환기를 추가해야합니다.이벤트 수신기 내부에 데이터 변환기를 추가하는 방법

나는 해결책이 간단 할 것이라고 생각했다. 폼에 PRE_SET_DATA 이벤트 리스너를 추가하고 (단지 기본 데이터에 액세스하기 위해) 필드와 트랜스 포머를 리스너 내부에 추가하기 만하면된다. 하지만 양식이 이미 잠겨 있기 때문에 수신기 내부에 변압기를 추가 할 수 없습니다.

많은 해결 방법을 시도했지만 해결할 수 없었습니다.

그것을 할 수있는 방법이 있나요 ... 내가 이벤트 리스너 내부 양식에 날짜 필드를 추가 할 때 데이터 변압기 그래서

$builder->... 
    ->add(
     $builder->create('date', 'choice', array(
      'label' => 'form.game.date', 
      'empty_value' => 'form.game.date', 
      'required' => false, 
      'choices' => array(
       '2014-04-10' => '10/Apr', // just to test 
       '2014-04-11' => '11/Apr', 
       ) 
      )) 
      ->addModelTransformer(new DateToStringTransformer()) 
     ); 

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

    $period = new \DatePeriod(
     $game->getTournament()->getBeginDate(), 
     new \DateInterval('P1D'), 
     $game->getTournament()->getEndDate()->add(new \DateInterval('P1D')) 
    ); 

    $dates = array(); 

    foreach($period as $date){ 
     $dates[$date->format("Y-m-d")] = $date->format("j/M"); 
    } 

    $form->add('date', 'choice', array(
     'label' => 'form.game.date', 
     'choices' => $dates, 
     )); 
}); 

는, 이전에 추가 된 데이터 필드를 교체 : 그녀는 내 코드입니까?

답변

0

나는 약간의 테스트를 작성하고 코드를 약간 업데이트했습니다. 귀하의 질문을 정확하게 이해했는지 확인하십시오.

SomeTypeTest.php :

<?php 
class SomeTypeTest extends TypeTestCase 
{ 
    /** 
    * @test 
    */ 
    public function testSubmitValidData() 
    { 
     $begin = new \DateTime(); 
     $formData = array(
      'date' => '2014-01-15' 
     ); 

     $type = new SomeType(); 
     $form = $this->factory->create($type); 

     $form->submit($formData); 

     $this->assertTrue($form->isSynchronized()); 
     $this->assertEquals(['date' => \DateTime::createFromFormat('Y-m-d', '2014-01-15')], $form->getData()); 

     $view = $form->createView(); 
     $children = $view->children; 

     foreach (array_keys($formData) as $key) { 
      $this->assertArrayHasKey($key, $children); 
     } 
    } 
} 

SomeType.php :

<?php 
class SomeType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($builder) { 
       //$game = $event->getData(); 
       $form = $event->getForm(); 

       $period = new \DatePeriod(
        \DateTime::createFromFormat('Y-m-d', '2014-01-01'), // for test 
        new \DateInterval('P1D'), 
        \DateTime::createFromFormat('Y-m-d', '2014-01-30') // for test 
       ); 

       $dates = array(); 

       foreach ($period as $date) { 
        $dates[$date->format("Y-m-d")] = $date->format("j/M"); 
       } 

       $form->add($builder->create('date', 'choice', array(
         'label' => 'form.game.date', 
         'empty_value' => 'form.game.date', 
         'auto_initialize' => false, 
         'required' => false, 
         'choices' => $dates 
        )) 
        ->addModelTransformer(new DateToStringTransformer())->getForm() 
       ); 
      }); 
    } 

    public function getName() 
    { 
     return 'st'; 
    } 
} 

DateToStringTransformer.php : 내가 관리했습니다

<?php 
class DateToStringTransformer implements DataTransformerInterface 
{ 
    /** 
    * @param mixed $value 
    * @return mixed|void 
    */ 
    public function transform($value) 
    { 
     if (!$value) { 
      return null; 
     } 

     return $value->format('Y-m-d'); 
    } 

    /** 
    * @param mixed $value 
    * @return mixed|void 
    */ 
    public function reverseTransform($value) 
    { 
     return \DateTime::createFromFormat('Y-m-d', $value); 
    } 
} 

https://gist.github.com/ChubV/11348928

+0

답변에이 코드를 삽입하십시오. 링크가 아닌 자체적으로 포함됩니다. –

+2

코드를 삽입했습니다. – Ziumin

+0

나는 또한 당신의 aproach를 시도했으며, 아마도 "$ builder-> addEventListener"를 호출하기 전에 일부 필드를 추가했기 때문에 이벤트 수신기 내부의 빌더를 사용할 수 없다. 그리고 그 순간에 양식은 이미 잠겨있다. 난 항상 데이터 변압기를 추가하는 사용자 지정 형식을 만들어서 작동하도록했습니다. 그런 다음 데이터 변압기를 놓치지 않고 모든 이벤트 리스너에서 "form-> add ('date', 'my_type', ..)를 호출 할 수 있습니다. 도움을 주셔서 감사합니다 –

0

가 작동하려면 작성자 : cre 항상 데이터 변환기를 추가하는 사용자 정의 유형에서. 그런 다음 데이터 변압기를 놓치지 않고 모든 이벤트 리스너에서 "form-> add ('date', 'my_type', ..)를 호출 할 수 있습니다.

MyType.php

class MyType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('field1') 
      ->add('field2') 
      ...; 

     $builder->addEventSubscriber(new AddDateSubscriber()); 
    } 
} 

CustomType.php

class DateChoiceType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->addModelTransformer(new DateToStringTransformer()); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'invalid_message' => 'The selected date does not exist', 
     )); 
    } 

    public function getParent() 
    { 
     return 'choice'; 
    } 

    public function getName() 
    { 
     return 'date_choice'; 
    } 
} 

나 데이터 변환기도 추가 될 폼 date_choice 유형을 추가 할 때마다. 이 사람을 도움이 될 것으로

class AddDateSubscriber implements EventSubscriberInterface 
{ 
    public static function getSubscribedEvents() 
    { 
     return array(FormEvents::PRE_SET_DATA => 'preSetData'); 
    } 

    public function preSetData(FormEvent $event) 
    { 
     $game = $event->getData(); 
     $form = $event->getForm(); 

     $endDate = \DateTime::createFromFormat('Y-m-d', $game->getTournament()->getEndDate()->format('Y-m-d')); 

     $period = new \DatePeriod(
      $game->getTournament()->getBeginDate(), 
      new \DateInterval('P1D'), 
      $endDate 
     ); 

     $dates = array(); 
     foreach($period as $date){ 
      $dates[$date->format("Y-m-d")] = $date->format("j/M"); 
     } 

     $form->add('date', 'date_choice', array(
      'label' => 'form.game.date.label', 
      'empty_value' => 'form.game.date.none', 
      'required' => false, 
      'choices' => $dates, 
      )); 
    } 
} 

DateToStringTransformer.php

class DateToStringTransformer implements DataTransformerInterface 
{ 
    public function transform($date) 
    { 
     if (null === $date) { 

      return ""; 
     } 

     return $date->format("Y-m-d"); 
    } 

    public function reverseTransform($stringDate) 
    { 
     if (!$stringDate) { 

      return null; 
     } 

     $date = \DateTime::createFromFormat('Y-m-d', $stringDate); 

     if (false === $date) { 

      throw new TransformationFailedException('Sting to date transformation failed!'); 
     } 

     return $date; 
    } 
} 

희망.

관련 문제