Symfony 2.8, 3.0 이상에서 buildForm ()에 데이터 전달


87

내 응용 프로그램은 현재이 답변 에서 권장하는 것처럼 생성자를 사용하여 내 양식 유형에 데이터를 전달합니다 . 그러나 Symfony 2.8 업그레이드 가이드 에서는 유형 인스턴스를 createForm함수에 전달하는 것은 더 이상 사용되지 않는다고 조언합니다 .

Form :: add (), FormBuilder :: add () 및 FormFactory :: create * () 메서드에 유형 인스턴스를 전달하는 것은 더 이상 사용되지 않으며 Symfony 3.0에서 더 이상 지원되지 않습니다. 대신 형식의 정규화 된 클래스 이름을 전달하십시오.

Before:    
$form = $this->createForm(new MyType());

After:
$form = $this->createForm(MyType::class);

정규화 된 클래스 이름으로 데이터를 전달할 수 없는데 대안이 있습니까?


1
어떤 종류의 데이터를 전달해야합니까? 주사 할 수있는 것입니까?
Cerad

2
UPGRADE.md가 개선 되기를
althaus

답변:


133

이로 인해 일부 양식도 깨졌습니다. 옵션 확인자를 통해 사용자 지정 데이터를 전달하여 문제를 해결했습니다.

양식 유형 :

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $this->traitChoices = $options['trait_choices'];

    $builder
        ...
        ->add('figure_type', ChoiceType::class, [
            'choices' => $this->traitChoices,
        ])
        ...
    ;
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'trait_choices' => null,
    ]);
}

그런 다음 컨트롤러에서 양식을 만들 때 생성자 대신 옵션으로 전달합니다.

$form = $this->createForm(ProfileEditType::class, $profile, [
    'trait_choices' => $traitChoices,
]);

8
이 문제도 만났고 비슷한 해결책을 찾았습니다. 데이터가 필요하고 생성자 정의에서 일반적으로 수행하는 유형 힌트를 수행하려면 configureOptions ()의 옵션 해결 프로그램에 대해 setRequired () 및 setAllowedTypes () 메서드를 사용해야한다고 생각합니다. , setDefaults () 대신.
sarahg 2015

2
그것이 바로 당신이해야 할 일입니다. :)
Bernhard Schussek

3
@Roubi는 동일한 작업을 수행하고 configureOptions 메서드에서 옵션을 정의한 다음 양식 필드를 추가 할 때 전달합니다.
Bart Wesselink

2
이 변화에 만족하지 않습니다. 그래도 대답 해 주셔서 감사합니다.
Adambean

2
FormType은 팩토리처럼 작동하며 상태 비 저장이어야합니다. 생성자를 통해 값을 주입하면 (서비스 태그 메서드를 통하지 않고) 상태 저장이됩니다. 이렇게하면 양식 유형을 만드는 하나의 균일 한 방법이 있습니다. 옵션은 항상 생성자 인수 대신 사용하기위한 것입니다. 이 변경은 DX와 유용성에 매우 좋습니다.
Anyone

6

여기에 다른 접근 방식을 사용할 수 있습니다-데이터 검색을위한 서비스 삽입.

  1. 귀하의 양식을 서비스로 설명하십시오 ( 요리 책 )
  2. 보호 필드 및 생성자를 추가하여 클래스를 형성하십시오.
  3. 필요한 데이터를 얻기 위해 주입 된 개체를 사용합니다.

예:

services:
    app.any.manager:
        class: AppBundle\Service\AnyManager

    form.my.type:
        class: AppBundle\Form\MyType
        arguments: ["@app.any.manager"]
        tags: [ name: form.type ]

<?php

namespace AppBundle\Form;

use AppBundle\Service\AnyManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MyType extends AbstractType {

    /**
     * @var AnyManager
     */
    protected $manager;

    /**
     * MyType constructor.
     * @param AnyManager $manager
     */
    public function __construct(AnyManager $manager) {
        $this->manager = $manager;
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $choices = $this->manager->getSomeData();

        $builder
            ->add('type', ChoiceType::class, [
                'choices' => $choices
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\MyData'
        ]);
    }

}

이것은 좋지만 서비스 관리자가 인수를 사용할 수 없으면 작동하지 않습니다.
demonkoryu

5

누군가 form.factory 서비스에서 'createNamedBuilder'또는 'createNamed'함수를 사용하는 경우이를 사용하여 데이터를 설정하고 저장하는 방법에 대한 스 니펫이 있습니다. 'data'필드를 사용할 수 없으며 (null 그대로 두십시오) 전달 된 데이터 / 항목을 $options값 으로 설정해야 합니다.

또한 setAllowedTypes () 및 setRequired () 옵션 사용에 대한 @sarahg 지침을 통합했으며 제대로 작동하는 것 같지만 먼저 setDefined ()로 필드를 정의해야합니다.

또한 양식 내에서 데이터를 설정해야하는 경우 '데이터'필드에 추가해야합니다.

컨트롤러에서는 2.8 / 3.0에서 getName이 더 이상 사용되지 않으므로 getBlockPrefix를 사용하고 있습니다.

제어 장치:

/*
* @var $builder Symfony\Component\Form\FormBuilderInterface
*/
$formTicket = $this->get('form.factory')->createNamed($tasksPerformedForm->getBlockPrefix(), TaskAddToTicket::class, null, array('ticket'=>$ticket) );

형태:

public function configureOptions(OptionsResolver $resolver)    {
    $resolver->setDefined('ticket');
    $resolver->setRequired('ticket');
    $resolver->addAllowedTypes('ticket', Ticket::class);

    $resolver->setDefaults(array(           
        'translation_domain'=>'AcmeForm',
        'validation_groups'=>array('validation_group_001'),
        'tasks' => null,
        'ticket' => null,
    ));
}

 public function buildForm(FormBuilderInterface $builder, array $options)   {

    $this->setTicket($options['ticket']);
    //This is required to set data inside the form!
    $options['data']['ticket']=$options['ticket'];

    $builder

        ->add('ticket',  HiddenType::class, array(
                'data_class'=>'acme\TicketBundle\Entity\Ticket',
            )
        )
...
}

5

다음은 Symfony 3을 사용하는 모든 사용자를 위해 데이터를 포함 된 양식에 전달하는 방법입니다. 먼저 위에 설명 된 @sekl을 정확히 수행 한 후 다음을 수행하십시오.

기본 FormType에서

' entry_options '를 사용하여 포함 된 양식에 var를 전달하십시오.

->add('your_embedded_field', CollectionType::class, array(
          'entry_type' => YourEntityType::class,
          'entry_options' => array(
            'var' => $this->var
          )))

포함 된 FormType에서

optionsResolver에 옵션 추가

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Yourbundle\Entity\YourEntity',
        'var' => null
    ));
}

buildForm 함수의 변수에 액세스하십시오. 빌더 기능 전에이 변수를 설정해야합니다. 제 경우에는 특정 ID를 기준으로 옵션을 필터링해야했습니다.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $this->var = $options['var'];

    $builder
        ->add('your_field', EntityType::class, array(
          'class' => 'YourBundle:YourClass',
          'query_builder' => function ($er) {
              return $er->createQueryBuilder('u')
                ->join('u.entity', 'up')
                ->where('up.id = :var')
                ->setParameter("var", $this->var);
           }))
     ;
}

혼란을 줄이려면-$ this-> var는 전달하려는 값이며 반드시 클래스 변수에서 가져 오지 않아도됩니다.
Darius.V
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.