php 在 Symfony 2.8、3.0 及更高版本中将数据传递给 buildForm()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34027711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 23:42:52  来源:igfitidea点击:

Passing data to buildForm() in Symfony 2.8, 3.0 and above

phpsymfony

提问by Jonathan

My application currently passes data to my form type using the constructor, as recommended in this answer. However the Symfony 2.8 upgrade guideadvises that passing a type instance to the createFormfunction is deprecated:

我的应用程序当前使用构造函数将数据传递给我的表单类型,如本答案中所推荐。但是Symfony 2.8 升级指南建议createForm不推荐将类型实例传递给函数:

Passing type instances to Form::add(), FormBuilder::add() and the FormFactory::create*() methods is deprecated and will not be supported anymore in Symfony 3.0. Pass the fully-qualified class name of the type instead.

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

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

将类型实例传递给 Form::add()、FormBuilder::add() 和 FormFactory::create*() 方法已被弃用,并且在 Symfony 3.0 中将不再受支持。改为传递类型的完全限定类名。

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

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

Seeing as I can't pass data through with the fully-qualified class name, is there an alternative?

看到我无法使用完全限定的类名传递数据,是否有替代方法?

回答by sekl

This broke some of our forms as well. I fixed it by passing the custom data through the options resolver.

这也破坏了我们的一些表格。我通过将自定义数据传递给选项解析器来修复它。

In your form type:

在您的表单中输入:

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

Then when you create the form in your controller, pass it in as an option instead of in the constructor:

然后,当您在控制器中创建表单时,将其作为选项而不是构造函数传入:

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

回答by Denis

Here can be used another approach - inject service for retrieve data.

这里可以使用另一种方法 - 注入服务来检索数据。

  1. Describe your form as service (cookbook)
  2. Add protected field and constructor to form class
  3. Use injected object for get any data you need
  1. 将您的表单描述为服务(食谱
  2. 添加受保护的字段和构造函数以形成类
  3. 使用注入的对象获取您需要的任何数据

Example:

例子:

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

}

回答by Ethernal

In case anyone is using a 'createNamedBuilder' or 'createNamed' functions from form.factory service here's the snippet on how to set and save the data using it. You cannot use the 'data' field (leave that null) and you have to set the passed data/entities as $optionsvalue.

如果有人使用 form.factory 服务中的“createNamedBuilder”或“createNamed”函数,这里是有关如何使用它设置和保存数据的片段。您不能使用“数据”字段(保留为空),并且必须将传递的数据/实体设置为$options值。

I also incorporated @sarahg instructions about using setAllowedTypes() and setRequired() options and it seems to work fine but you first need to define field with setDefined()

我还合并了有关使用 setAllowedTypes() 和 setRequired() 选项的 @sarahg 说明,它似乎工作正常,但您首先需要使用 setDefined() 定义字段

Also inside the form if you need the data to be set remember to add it to 'data' field.

如果您需要设置数据,请记住将其添加到“数据”字段中。

In Controller I am using getBlockPrefix as getName was deprecated in 2.8/3.0

在控制器中我使用 getBlockPrefix 因为 getName 在 2.8/3.0 中被弃用

Controller:

控制器:

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

Form:

形式:

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

回答by mcriecken

Here's how to pass the data to an embedded form for anyone using Symfony 3. First do exactly what @sekl outlined above and then do the following:

以下是如何将数据传递给任何使用 Symfony 3 的人的嵌入式表单。首先完全按照上面的@sekl 进行操作,然后执行以下操作:

In your primary FormType

在您的主要 FormType 中

Pass the var to the embedded form using 'entry_options'

使用“ entry_options”将var传递给嵌入的表单

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

In your Embedded FormType

在您的嵌入式 FormType 中

Add the option to the optionsResolver

将选项添加到 optionsResolver

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

Access the variable in your buildForm function. Remember to set this variable before the builder function. In my case I needed to filter options based on a specific ID.

访问 buildForm 函数中的变量。请记住在 builder 函数之前设置此变量。就我而言,我需要根据特定 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);
           }))
     ;
}