在Symfony 2.8,3.0及更高版本

时间:2015-12-01 18:41:56

标签: php symfony

我的应用程序当前使用构造函数将数据传递给我的表单类型,如this answer中所建议的那样。但是Symfony 2.8 upgrade guide建议不要弃用将类型实例传递给createForm函数:

  

将类型实例传递给Form :: add(),FormBuilder :: add()和   不推荐使用FormFactory :: create *()方法,不支持这些方法   在Symfony 3.0中。传递完全限定的类名   改为输入。

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

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

看到我无法通过完全限定的类名传递数据,还有其他选择吗?

4 个答案:

答案 0 :(得分:124)

这也打破了我们的一些形式。我通过选项解析器传递自定义数据来修复它。

在表单中输入:

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

答案 1 :(得分:6)

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

  1. 将您的表单描述为服务(cookbook
  2. 将受保护的字段和构造函数添加到表单
  3. 使用注入的对象获取所需的任何数据
  4. 示例:

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

答案 2 :(得分:5)

如果有人在form.factory服务中使用'createNamedBuilder'或'createNamed'函数,那么这里有关于如何使用它设置和保存数据的代码片段。您不能使用'data'字段(保留null),您必须将传递的数据/实体设置为$options值。

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

定义字段

如果您需要设置数据,请在表单内部记住将其添加到“数据”字段。

在Controller中我使用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',
            )
        )
...
}

答案 3 :(得分: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
          )))

在您的Embedded 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);
           }))
     ;
}