【问题标题】:Symfony form event: ChoiceType field return null unexpectedlySymfony 表单事件:ChoiceType 字段意外返回 null
【发布时间】:2017-06-10 23:31:23
【问题描述】:

我正在处理 symfony 表单,我在字段中使用 select2 进行 ajax 请求,我监听 PRE_SUBMIT 事件以获取选项列表并提供给 choices 选项

$opts = $config->getOptions();
$opts['choices'] = $listImages; //array of Image object

但是在 var_dump 的 PRE_SUBMIT 事件中,我在表单中获取选定的值,并在闭包中使用它,并且当持久化该字段时,该字段具有空值,所以我在 POST_SUBMIT 事件中执行 var_dump该字段确实具有 null 作为值。而且我没有看到我错过了什么

我的 FormType 如下:

class ArticleType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('image', ChoiceType::class, array(
            'expanded' => false,
            'multiple' => false))
        //other field
        ;

       $formModifier = function (FormInterface $form, $image) use ($options) {
        $listImages = $options['em']->getRepository('AlmotivAppBundle:Image')->findBy(array(
            'id' => $image
        ));

        if (!$listImages) {
            $form->add('image')->addError(new FormError(
                'Nous n\'avons pas p trouver l\'image, veuiller choisir une autre'
            ));
        }
        //die(var_dump($listImages)); //array of Image object


        $config = $form->get('image')->getConfig();
        $opts = $config->getOptions();
        $opts['choices'] = $listImages;
        $typeName = get_class($config->getType()->getInnerType());
        $form->add('image', $typeName, $opts);
        //die(var_dump($form->get('image')->getConfig()->getData())); //return null
    };

    $builder->get('image')->addEventListener(
        FormEvents::PRE_SUBMIT,
        function (FormEvent $event) use ($formModifier) {
            $image = $event->getData();
            //die(var_dump($image)); //return 10
            $formModifier($event->getForm()->getParent(), $image);
        }
    );

我正在使用框架的 v3.1。 如果您需要更多,请询问。

【问题讨论】:

    标签: php forms symfony symfony-forms symfony-3.1


    【解决方案1】:

    这似乎是在那个时间点返回的完全有效的值。

    PRE_SUBMIT 期间,您会获得父表单并将其传递给$formModifier,这没关系。但是,除其他外,该修饰符会执行以下操作:

    $typeName = get_class($config->getType()->getInnerType());
    $form->add('image', $typeName, $opts);
    

    您的表单中已经有一个名为image 的字段,但重新添加它会完全覆盖其上下文(包括数据)。在您查看Form.php 时,您会看到:

    Form.php 第 873 行

    $this->children[$child->getName()] = $child;
    

    也就是说,一旦表单域重叠,您将无法检索数据。

    为什么重新添加字段后需要检索数据?

    【讨论】:

    • 要将其保存在数据库中,该字段具有ManyToOne 关系,因此我需要将所选选项的值传递给Doctrine,如果我不会收到类似值的错误无效。正如我所看到的,您无法在构建后更改字段的配置,如果我错了,请纠正我,但您可以覆盖它,所以我做到了并且知道我丢失了数据。现在的问题是如何在不丢失数据字段的情况下将imagesList 传递给$options[choices]
    • 和@JovanPerovic 我不认为重新添加该字段是一个问题,因为当我将$event 传递给闭包并在POST_SUBMIT 事件中执行$event->getData(); 时,我收到了提交的数据,然后我在 PRE_SUBMIT 事件中重新添加该字段,而神秘的是在 POST_SUBMIT 中执行 $event->getForm(); 时,我的图像字段具有 null 值,而我的其他字段具有正确的值。我该如何处理?
    • 我有两个解决方案来处理这个问题 1- 是我自己在表单中设置数据,因为我不明白为什么图像总是得到空值。 2-使用未映射,然后在事件中添加我的图像字段和提交的文本类型的数据(我认为这不是最好的方法(因为图像与我的文章实体有很多关系),但这是我唯一的一个找到)
    • 无法回答,所以问题是使用EntityType,然后使用表单事件,在本例中为PRE_SUBMITPRE_SET_DATA,传递“选择”的可能性到字段选项。我创建了一个gist 来分享
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    相关资源
    最近更新 更多