Symfony注入参数以从buildForm形成

时间:2018-08-29 08:56:20

标签: php symfony symfony-forms

我正在使用Symfony <4,并且我在使用带有参数的多对多关系的其他表单的表单时遇到问题。

您将在我的FeatureForm下方找到:

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

现在我的TagFeatureType:

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

我想将参数注入到findOBjectNotMine中,但是由于TagFeatureType由FeatureForm创建,因此无法从控制器传递参数。在buildForm函数内部,我无法传递任何额外的参数。

我看到2种可能性,首先,我修改了默认选项以允许有一个额外的选项,但这有点令人作呕。第二,我可以在构造函数中使用会话参数并注入会话服务...但是,看起来它似乎是一种替代方法,而不是正确的方法...

您知道从FormType内部的buildForm函数中向表单注入参数的一种优雅方法吗?

最诚挚的问候

2 个答案:

答案 0 :(得分:1)

如果需要将容器已知的参数传递给自定义表单类型,则可以按照上面的尝试进行操作(显然是通过参数注入)。但是,如果要将数据从控制器向下传递到表单类型,则可以通过$options(最后一个)参数(在buildForm中)传递数据:

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

然后,在TagFeatureType中应配置选项:

TagFeatureType

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

最后,将其包含在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);
        }
    );

    // ....
}

显而易见的缺点是,路径中的所有表单都必须具有setRequiredsetDefault

希望这对您有帮助...

答案 1 :(得分:0)

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

有一个DependencyInjectionExtension form extension,它将检查表单类型是否已在服务容器中注册,然后注入它,而不是创建新实例。这应该确保标记存储库存在。