简体   繁体   English

Symfony注入参数以从buildForm形成

[英]Symfony inject parameter to form from buildForm

I'm using Symfony <4 and I have an issue with a form using an other form in a Many-To-Many relation with parameter. 我正在使用Symfony <4,并且在使用带有参数的多对多关系中的其他表单的表单时遇到问题。

You will find below my FeatureForm: 您可以在我的FeatureForm下面找到:

            ->add('tags',CollectionType::class,
            array(
                'entry_type' =>TagFeatureType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'data' => $datas,
                'entry_options' => array(
                    'label' => false,
                )
            )
        )

Now my TagFeatureType: 现在我的TagFeatureType:

            ->add('tag', EntityType::class,
            array(
                'choice_label' => 'name',
                'class' => 'AppBundle:Tag',
                'query_builder' => function(TagRepository $tr){
                    return $tr->findObjectNotMine();
                }
            )
        )

I would like to inject a parameter into findOBjectNotMine but I cannot pass parameter from controller because the TagFeatureType is created by FeatureForm. 我想将参数注入findOBjectNotMine中,但由于TagFeatureType由FeatureForm创建,因此无法从控制器传递参数。 Inside the buildForm function I cannot pass any extra parameter. 在buildForm函数内部,我无法传递任何额外的参数。

I see 2 possibilites, 1st I modify default options to allow an extra option, but it's a bit disgusting. 我看到2种可能性,第一种是我修改了默认选项以允许额外的选项,但这有点令人作呕。 2nd, I could use session parameter and inject session service inside the constructor... But it looks like more a workaround than a proper way... 第二,我可以在构造函数内部使用会话参数并注入会话服务...但是,这看起来似乎是一种替代方法,而不是正确的方法...

Do you know an elegant way to inject parameter to a form from buildForm function inside FormType? 您知道从FormType内部的buildForm函数将参数注入表单的一种优雅方法吗?

Best regards 最好的祝福

In case you need to pass container-known parameters to custom form type, you can go the way you attempted above (obviously via parameter injection). 如果需要将容器已知的参数传递给自定义表单类型,则可以按照上面的尝试进行操作(显然是通过参数注入)。 However, if you want to pass data from controller down to form type, you can pass it via $options (last) argument (in buildForm ): 但是,如果要将数据从控制器向下传递到表单类型,可以通过$options (最后一个)参数(在buildForm )传递数据:

FeatureForm FeatureForm

public function buildForm(FormBuilderInterface $builder, array $options)

    // ....

    $builder->add('tags', CollectionType::class, array (
           'entry_type' => TagFeatureType::class,
           'allow_add' => true,
           'allow_delete' => true,
           'data' => $datas,
           'entry_options' => array(
               'label' => false,
               'some_custom_param' => $options['some_custom_param']
           )
       )
    );

    // ....
 }

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

And then, in TagFeatureType should have configured options: 然后,在TagFeatureType应该配置选项:

TagFeatureType TagFeatureType

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setRequired(array(
        'some_custom_param'
    ));
}

And then finally, include it inside of buildForm : 最后,将其包含在buildForm

public function buildForm(FormBuilderInterface $builder, array $options)

    // ....
    $someCustomParam = $options['some_custom_param'];

    // .... 

    $builder->add('tag', EntityType::class, array(
        'choice_label' => 'name',
        'class' => 'AppBundle:Tag',
        'query_builder' => function(TagRepository $tr) use ($someCustomParam) 
        {
            return $tr->findObjectNotMine($someCustomParam);
        }
    );

    // ....
}

Obvious downside of this would be a need for all the forms in path to have setRequired or setDefault . 明显的缺点是,路径中的所有表单都必须具有setRequiredsetDefault

Hope this helps... 希望这可以帮助...

In your TagFeatureType you can just pass in the argument via constructor injection: 在TagFeatureType中,您可以通过构造函数注入传递参数:

class TagFeatureType extends AbstractType
{
    private $tagRepository;

    public function __construct(TagRepository $tagRepository)
    {
        $this->tagRepository = $tagRepository;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $tr = $this->tagRepository;
        // ...
        ->add('tag', EntityType::class,
            array(
                'choice_label' => 'name',
                'class' => 'AppBundle:Tag',
                'query_builder' => function(TagRepository $tr){
                    return $tr->findObjectNotMine();
                }
            )
        )
    }
}

There is a DependencyInjectionExtension form extension that will check if the form type is registered in the service container and then inject it, instead of creating a new instance. 有一个DependencyInjectionExtension表单扩展 ,它将检查表单类型是否在服务容器中注册,然后注入它,而不是创建新实例。 This should make sure that the tag repository exists. 这应该确保标记存储库存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM