4

在我的应用程序中,用户可以为某些实体创建自定义字段,然后在我显示表单时为每个实体对象设置此自定义字段的值。

实现是这样的:

1º)我为表单创建了一个接口,我想要实现这个接口的表单。

2º)我为所有表单创建了一个表单扩展:

app_core_form_builder.form_extension:
        class: App\Core\Bundle\FormBuilderBundle\Form\FormExtension
        arguments: ["@service_container", "@doctrine.orm.entity_manager"]
        tags:
            - { name: form.type_extension, alias: form }

3º) 在这个扩展中,如果表单实现了步骤 1 中引用的接口,我添加一个 EventSubscriber:

if($formType instanceof \App\Core\Bundle\FormBuilderBundle\Model\IAllowCustomFieldsdInterface){
             $builder->addEventSubscriber(new FormSubscriber($this->container, $this->em));    
}

4º) 此表单订阅者订阅 preSetData FormEvent。在这种方法中,我获得了与表单关联的实体,并获得了为其创建的所有自定义字段。然后我在 Symfony2 Form Type 的帮助下将此字段添加到表单中。一切顺利,当我显示我的表单时,自定义字段呈现正确。仅作记录,当我保存表单时,自定义字段中插入的值也可以很好地存储。

public function preSetData(FormEvent $event) {

        $data = $event->getData();
        $form = $event->getForm();


        // During form creation setData() is called with null as an argument
        // by the FormBuilder constructor. You're only concerned with when
        // setData is called with an actual Entity object in it (whether new
        // or fetched with Doctrine). This if statement lets you skip right
        // over the null condition.
        if (null === $data) {
            return;
        }

        $formEntity = $form->getConfig()->getType()->getInnerType()->getEntity();

        $DbEntity = $this->em->getRepository('AppCoreSchemaBundle:DbEntity')->findOneBy(array('id' => $formEntity));

        if ($DbEntity && $DbEntity->getAllowCustomFields()) {

            $organization = $this->container->get('app_user.user_manager')->getCurrentOrganization();

            if (!$organization) {
                throw $this->createNotFoundException('Unable to find Organization entity.');
            }

            $params = array(
                'organization' => $organization,
                'entity' => $DbEntity,
            );

            $entities = $this->em->getRepository('AppCoreSchemaBundle:DbCustomField')->getAll($params);


            # RUN BY ALL CUSTOM FIELDS AND ADD APPROPRIATE FIELD TYPES AND VALIDATORS
            foreach ($entities as $customField) {
                # configurate customfield

                FieldConfiguration::configurate($customField, $form);
                # THE PROBLEM IS HERE
                # IF OBJECT IS NOT NULL THEN MAKE SET DATA FOR APPROPRIATED FIELD
                if ($data->getId()) {

                    $filters = array(
                        'custom_field' => $customField,
                        'object' => $data->getId(),
                    );

                    $DbCustomFieldValue = $this->em->getRepository('UebCoreSchemaBundle:DbCustomFieldValue')->getFieldValue($filters);
                if ($DbCustomFieldValue) {
                    $form[$customField->getFieldAlias()]->setData($DbCustomFieldValue->getValue());
                } else {
                    $form[$customField->getFieldAlias()]->setData(array());
                }
                }
            }
        }
    }

问题是当我尝试编辑表单时。如果您查看上面代码中“问题在这里”的部分,您就可以理解。

如果表单的对象具有 ID,那么我将获取为该对象的自定义字段存储的值,然后调用 $form[field_alias']->setData(从映射为数组类型的数据库返回的值)。

但这不起作用,并且没有为字段设置数据。但如果在我的控制器中我也这样做,则数据设置正确。

有人知道问题出在哪里吗?我不能在 preSetData 事件中设置数据吗?

已编辑

Entity DbCustomField 中的值字段以这种方式映射:

/**
     * @var string
     *
     * @ORM\Column(name="value", type="array", nullable=true)
     */
    protected $value;

`

var_dump($DbCustomFieldValue)-> 对象(Ueb\Core\Bundle\SchemaBundle\Entity\DbCustomFieldValue)

var_dump(DbCustomFieldValue->getValue())

-> 字符串(11)“布鲁诺勇气”

但即使我尝试类似:

var_dump($customField->getFieldAlias());= 字符串(21)“testebruno-1383147874”

$form[$customField->getFieldAlias()]->setData('example1');它不起作用。

但是在我的控制器中,如果我对上面的 fieldAlias 执行以下操作:

$form['testebruno-1383147874']->setData('example2');

-> 它确实有效

任何想法?

4

1 回答 1

1

正如metalvarez在他/她的评论中建议的那样并按预期工作,使用postSetData事件而不是事件preSetData

public function postSetData(FormEvent $event) {
    // ...
}

preSetData使用默认值填充表单之前调用 event 方法,然后 Symfony2 将设置数据,它可能会与您之前设置的不同,因此使用postSetData代替。

在此处输入图像描述

来自文档

于 2015-04-11T12:55:23.533 回答