Php Symfony2表单:根据表单值设置默认选项

Php Symfony2表单:根据表单值设置默认选项,php,forms,symfony,Php,Forms,Symfony,我使用的是Symfony2框架(特别是Symfony2.7)。我的问题是关于建筑的 我有一个名为place的实体,它可以与我的项目的许多其他实体关联。因此,我创建了一个自定义表单类型,可以在应用程序的许多部分中重用 class PlacesType extends AbstractType { private $security_context; public function __construct(SecurityContext $security_context)

我使用的是Symfony2框架(特别是Symfony2.7)。我的问题是关于建筑的

我有一个名为place的实体,它可以与我的项目的许多其他实体关联。因此,我创建了一个自定义表单类型,可以在应用程序的许多部分中重用

class PlacesType extends AbstractType
{

    private $security_context;

    public function __construct(SecurityContext $security_context)
    {
        $this->security_context = $security_context;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $user = $this->security_context->getToken()->getUser();

        parent::configureOptions($resolver);

        $resolver->setDefaults(array(
            'class' => 'AppBundle\Entity\Places',
            'query_builder' => function (EntityRepository $repository) use ($user)
            {
                return $repository->queryPlacesForUser($user);
            },
        ));

    }

    public function getParent()
    {
        return 'entity' ;
    }

    public function getName()
    {
        return 'places';
    }
}
事实上,可以软删除位置(我在类中设置了删除标志)。因此,新实体只能关联到活动位置,而旧实体可以保持与现在已删除位置的关联

因此,我希望queryplacesfourser函数只返回活动位置,除非该位置已与父级表单数据关联。
大概是这样的:

    public function configureOptions(OptionsResolver $resolver)
    {
        // ...

        $currdata = $this->getForm()->getData(); // pseudo-code, this does not work

        $resolver->setDefaults(array(
            'class' => 'AppBundle\Entity\Places',
            'query_builder' => function (EntityRepository $repository) use ($user)
            {
                return $repository->queryPlacesForUser($user, $currdata);
            },
        ));

    }
不幸的是,我不知道如何从选项解析器获取当前数据。可以在表单的buildForm函数中检索当前数据,但无法在其中设置表单选项


是否有一种方法可以使用表单传递的数据设置表单默认选项?

您可以使用这样的事件侦听器:

    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
                    $data = $event->getData();
                    $form = $event->getForm();
    //check your data here and add the fields you want accordingly

$field = $builder->get('fieldToModify');         // get the field
$options = $field->getOptions();            // get the options
$type = $field->getType()->getName();       // get the name of the type
$options['label'] = "Login Name";           // change the label
$builder->add('fieldToModify', $type, $options); // replace the field
        }

您无权访问
configureOptions
中的表单数据。添加了一个约束,即您只想预配置/重新配置扩展类型,我认为,唯一的选择是将所需的配置提取到使用此自定义表单类型的位置。例如:

用法

<?php

/**
 * @inheritdoc
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $this->builder->add('place', PlacesType::class, [
        'only_active' => false // <- this is the *external* configuration
    ]);
}
<?php

/**
 * @inheritdoc
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'class' => 'AppBundle\Entity\Places',
        'only_active' => true, // <- this is the *default* configuration

        // note the extra closure, this gives you access to the *resolved* options.
        'query_builder' => function (Options $options) { 
            return function (EntityRepository $repository) use ($options) {
                return $repository->queryPlacesForUser(
                    $this->security_context->getToken()->getUser(),
                    $options['only_active']
                );
            };
        },
    ));
}

您是否愿意在使用此自定义表单类型的代码中插入所需的配置数据?不,我考虑过,但您将失去共享表单类型的好处。老实说,我认为这是您唯一的选择。它和注入表单数据没什么不同,不是吗?我将添加一个答案来说明我的意思。感谢您的回答,但我并不是要在表单中添加子项,而是要设置当前子项的选项。谢谢您的帮助。我使用了你的答案(我直接通过了选项中的当前位置),但我仍然不太喜欢它。在我使用places表单类型的地方,我不得不修改大约20个表单,我项目的其他实体也可以采用相同的方式。我更喜欢一个更具可扩展性的解决方案。@Alberto我理解,而且我自己也多次遇到过这个特定的障碍。问题实际上只是因为您希望根据基础数据更改扩展类型的默认值。直到今天,我还没有找到更好的解决方案,尽管我真的很想看到一个。