Передача данных в buildForm () в Symfony 2.8 / 3.0

Мое приложение в настоящее время передает данные в мой тип формы с использованием конструктора, как это рекомендовано в этом ответе . Однако руководство по обновлению Symfony 2.8 сообщает, что передача экземпляра createForm функции createForm устарела:

Коды экземпляров типа Form :: add (), FormBuilder :: add () и FormFactory :: create * () устарели и больше не будут поддерживаться в Symfony 3.0. Вместо этого передайте полностью квалифицированное имя класса.

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

Видя, как я не могу передать данные с помощью полностью квалифицированного имени класса, есть ли альтернатива?

Это нарушило и некоторые наши формы. Я исправил его, передав пользовательские данные через опцию resolver.

В вашей форме:

 public function buildForm(FormBuilderInterface $builder, array $options) { $this->traitChoices = $options['trait_choices']; $builder ->add('name', TextType::class, ['label' => 'L_PROFILE_EDIT_NAME', 'required' => false]) ... ->add('figure_type', ChoiceType::class, [ 'label' => 'L_PROFILE_EDIT_FIGURETYPE', 'mapped' => false, 'choices' => $this->traitChoices['figure_type'] ]) ... ; } /** * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'Foo\BarBundle\Entity\Profile', 'trait_choices' => null, )); } 

Затем, когда вы создаете форму в своем контроллере, передайте ее как вариант, а не в конструкторе:

 $form = $this->createForm(ProfileEditType::class, $profile, array( 'action' => $this->generateUrl('profile_update'), 'method' => 'PUT', 'trait_choices' => $traitChoices, )); 

В случае, если кто-либо использует функции createNamedBuilder или createNamed из сервиса form.factory, здесь приведен фрагмент того, как установить и сохранить данные с его помощью. Вы не можете использовать поле данных (оставить это значение null), и вам необходимо установить переданные данные / сущности в качестве значения $options .

Я также добавил инструкции @sarahg об использовании параметров setAllowedTypes () и setRequired () и, похоже, работает нормально, но сначала вам нужно определить поле с помощью setDefined ()

Также внутри формы, если вам нужны данные, которые необходимо установить, не забудьте добавить их в поле «данные».

В контроллере я использую getBlockPrefix, поскольку getName устарел в 2.8 / 3.0

контроллер:

 /* * @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', ) ) ... } 

Вот как передать данные во встроенную форму для тех, кто использует Symfony 3. Сначала сделайте точно, что @sekl изложил выше, а затем выполните следующие действия:

В вашем основном FormType

Передайте var во встроенную форму, используя ' entry_options '

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

В вашем встроенном типе формы

Добавьте опцию в опцииРезольвер

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

Получите доступ к переменной в вашей функции buildForm. Не забудьте установить эту переменную перед функцией построителя. В моем случае мне нужно было отфильтровать параметры на основе определенного идентификатора.

 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); })) ; } 

Здесь можно использовать другой подход – внедрить службу для извлечения данных.

  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' ]); } }