Symfony 扩展了一个表单,依赖于提交数据

Symfony extends a form with dependencies from submit data

我正在尝试扩展我的表格,但我不知道该怎么做...

问题

我的父 formType 取决于一个选项。但我想从子表单中提供该选项。在 symfony documentation 中,他们解释了一种添加依赖于提交数据的动态字段的方法。但是如果它有一个带有 DataTransformer 的字段?,因为在 FormInterface 中我无法添加它。

代码

class TransactionApiType extends AbstractApiType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $app = $options['app'];
         
         $builder
            ->add('gamer', TextType::class)->addModelTransformer(new GamerExternalIdToStringCreateIfNotExistTransformer($em, $app))
            ;
    }
    
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
           'data_class' => Transaction::class,
        ))
           ->setAllowedTypes('app', ['AppBundle\Entity\App'])
    ;
    }

}


class TransactionMultiAppConfByAppApiType extends TransactionApiType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('app_id',
           EntityType::class,
           [
           'property_path' => 'app',
           'required'      => true,
           'description'   => 'App id',
           'class'         => App::class,
        ])
       ;

       // I need pass $options['app'] here to work (App will be submitted),
       // How can do? or other possibilities
       parent::buildForm($builder, $options);

    }

    public function configureOptions(OptionsResolver $resolver)
    {
       $resolver->setDefaults(array(
        'data_class' => Transaction::class,
        )
        ;
    }
}

提前致谢:-)

在 formEvents 中使用 DataTransformers 添加字段未启用https://github.com/symfony/symfony/issues/9355

但是有一个"hack" 相关这里Symfony2 form events and model transformers(总结它需要创建一个customType ...)

我的解决方案是

class TransactionMultiAppConfByAppApiType extends TransactionApiType
{

    // ...
    parent::buildForm($builder, $options);

    $optionsApp = $builder->get('gamer')->getAttributes()['data_collector/passed_options'];
    $builder->remove('gamer');

    $builder->get('app_id')->addEventListener(
        FormEvents::POST_SUBMIT,
        function (FormEvent $event) use ($em, $optionsApp) {

            /** @var App $app */
            $app = $event->getForm()->getData();
            $f = $event->getForm()->getParent();

            if ($app)
            {
                $f
                    ->add('gamer', GamerIdWithExternalIdCustomType::class, $optionsApp + ['em' => $em, 'app' => $app])
                ;
            }

    });

    // ...

}

class GamerIdWithExternalIdCustomType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addModelTransformer(new GamerExternalIdToStringCreateIfNotExistTransformer($options['em'], $options['app']));
    }

    public function getParent()
    {
        return TextType::class;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
    $resolver
        ->setRequired([
            'em',
            'app',
        ]);
    }
}