用动态表单元素填充教义表单

时间:2015-03-10 10:05:07

标签: symfony doctrine-orm twig

我目前正在开发一个Symfony2项目,而且我一直在创建表单。我有以下设置:

<?php
class Field {
private $name;
private $label;
private $type;
/**
 * @ORM\OneToMany(targetEntity="Option", mappedBy="field")
 */
private $options;

....
?>

<?php
class Option {
private $value;
private $type;
/**
 * @var string
 * 
 * @ORM\ManyToOne(targetEntity="Field", inversedBy="options")
 * @ORM\JoinColumn(name="field", referencedColumnName="name")
 */
private $field;

....
?>

现在,我想做什么,我正在创建一个表单,将'field'作为下拉/选项列表/ radiobutton / checkbox组(由Field :: $ type指定)并填写这个领域有它的选择。有什么想法吗?

编辑:重要的是:我不需要添加,删除或更改选项的功能。它们在数据库中修复,只需要从中选择。有些人与多人,有些没有。

Edit2:只是为了澄清:我正在使用Symfony Forms构建表单:我有一个基本表单类型(“Case”),其中包含包含其选项的Fields:

class CaseType extends AbstractType
{
    private $case;
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $this->case = $options['data'];
        $builder
            ->add('user')
            ->add('fields', 'collection', array('type' => new FieldType()))
        ;

class FieldType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->add('options', 'entity', array(
                    "class"     => "MyBundle:Option",
                    "property"  => "value",
                    "query_builder" => function (EntityRepository $er) {
                        return $er->createQueryBuilder('o', 'Option')
                            ->where('o.field = :f')
                            ->setParameter('f', **type_of_current_field**)
                            ->orderBy('o.value', "ASC");
                    }
        ));

这不能按预期工作......首先是因为我无法访问字段 - &gt;类型,其次是相当混乱

Edit3:好的,我绝对不明白为什么这不起作用:

class FieldType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $formFactory = $builder->getFormFactory();
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) {
            $form = $event->getForm();
            $data = $event->getData();

            $form->add('options', 'entity', array(
                    "class"     => "MyBundle:Option",
                    "property"  => "value",
                    "multiple"  => "true",
            ));
        });

... ?&GT;

这只是给出了以下错误:     警告:为foreach()提供的参数无效

我不应该只解析一个字段的所有选项吗?或者我的方法是完全错误的,我应该做的不同?当我转出我的字段时,它看起来像这样:

Field {#427 ▼
  -id: 26
  -name: "MyField"
  -label: "field to fill out"
  -type: "D"
  -public: 1
  -options: PersistentCollection {#440 ▼
    -snapshot: array:2 [ …2]
    -owner: Field {#427}
    -association: array:15 [ …15]
    -em: EntityManager {#289 …10}
    -backRefFieldName: "field"
    -typeClass: ClassMetadata {#401 …}
    -isDirty: false
    -initialized: true
    -coll: ArrayCollection {#397 ▼
      -_elements: array:2 [▼
        0 => Option {#435 ▼
          -id: 91
          -value: 1
          -field: Field {#427}
          -type: "D"
        }
        1 => Option {#432 ▼
          -id: 92
          -value: 2
          -field: Field {#427}
          -type: "D"
        }
      ]
    }
  }
}

2 个答案:

答案 0 :(得分:0)

你可以扩展的非常基本的例子。

{% for f in fields %}
    {% if f.type == 'select' %}
        <select>
        {% for o in f.options %}
              <option value="{{ o.value }}">{{ o.value }}</option>
        {% endfor %}
        </select>
    {% endif %}
{% endfor %}

答案 1 :(得分:0)

我找到了解决方案。问题是,Doctrine&lt; 2.5在加载Fields时会自动加载所有选项。所以我设法创建了一个解决方法:

$formFactory = $builder->getFormFactory();
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) {
            $form = $event->getForm();
            $this->field = $event->getData();

            $form->add('options', 'entity', array(
                    "class"     => "MyBundle:Option",
                    "property"  => "value",
                    'query_builder' => function(EntityRepository $er) {
                        return $er->createQueryBuilder('o')
                            ->where('o.field = :field')
                            ->setParameter('field', $this->field->getName())
                            ->orderBy('o.value', 'ASC');
                    },
            ));
        });

更合适的解决方案是等待Doctrine 2.5,然后只使用他们提供的新功能:fetch =&#34; EAGER&#34;对于OneToMany-Relationships,但它以这种方式工作。