Передача данных в buildForm () в Symfony 2.8 / 3.0
мое приложение в настоящее время передает данные в мой тип формы с помощью конструктора, как рекомендовано в этом ответе. Однако 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);
поскольку я не могу передать данные с полным именем класса, есть ли альтернатива?
4 ответа:
это сломало некоторые из наших форм. Я исправил это, передав пользовательские данные через распознаватель параметров.
в виде:
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" из формы.заводская служба Вот фрагмент о том, как установить и сохранить данные с его помощью. Вы не можете использовать поле "Данные" (оставьте это значение 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', ) ) ... }
здесь может быть использован другой подход - внедрить сервис для получения данных.
- опишите вашу форму как сервис (рецепты)
- добавить защищенное поле и конструктор для формирования класса
- используйте введенный объект для получения любых данных, которые вам нужны
пример:
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' ]); } }
вот как передать данные во встроенную форму для всех, кто использует Symfony 3. Сначала сделайте именно то, что @sekl изложил выше, а затем сделайте следующее:
в вашем основном FormType
передайте var во встроенную форму с помощью ' entry_options'
->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 )); }
доступ к переменной в вашей форме построения функция. Не забудьте установить эту переменную перед вызовом функции застройщика. В моем случае мне нужно было фильтровать параметры на основе определенного идентификатора.
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); })) ; }