如何访问集合扩展中的集合成员标签

时间:2014-01-08 18:46:49

标签: symfony symfony-forms

我已使用collection扩展了CollectionTableExtension表单字段类型。我正在尝试设置变量FormView::$vars['headers'],以便在collectionis_table并且没有用户定义的标头可用时,可以使用默认标头输出true。默认标题应与通常应用于集合成员的标签相同。

e.g。

如果FooType有3个字段foobarfibble,则其标签将为Foo,Bar和Fibble(使用Twig模板进行人性化后)或值存储在每个属性的label属性中。

因此,如果我的DoofusType收藏了FooType s,

$builder->add('foos', 'collection', array('type'=>'acc_foo', 'is_table'=>true));

应该会产生一个视图,其中集合的标题将是Foo,Bar和Fibble,或FooType的标签属性值(如果已设置)。

这是我的collection扩展程序:

<?php
namespace ACC\MainBundle\Form;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CollectionTableExtension extends AbstractTypeExtension
{

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setOptional(array('is_table'));
        $resolver->setOptional(array('headers'));
        $resolver->setOptional(array('caption'));
    }

    public function getExtendedType()
    {
        return 'collection';
    }


    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        if (array_key_exists('is_table', $options)) {
            $view->vars['is_table'] = $options['is_table'];

            if (array_key_exists('caption', $options))  $view->vars['caption'] = $options['caption'];   

            if (array_key_exists('headers', $options)) {
                $view->vars['headers'] = $options['headers'];
            }else{
                //harvest labels from  collection members, but HOW?
            }
        }
    }

}

问题是我不知道如何从集合扩展中访问集合元素类型的属性。我可以像这样访问集合中的第一个元素:

if($form->has('0')) {
    foreach($form->get('0')->all() as $item)
        $view->vars['headers'][] = $item->getName();
}

但如果集合为空,则无效。如果集合元素类型已定义标签,则无效。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

经过Symfony源代码的大量扫描后,我找到了一种方法。实质上,在::buildView中,必须实例化正确类型的虚拟集合元素,以便可以提取其标签或属性。这是我做的:

public function buildView(FormView $view, FormInterface $form, array $options)
{
    if (array_key_exists('is_table', $options)) {
        $view->vars['is_table'] = $options['is_table'];

        if (array_key_exists('caption', $options))  $view->vars['caption'] = $options['caption'];   

        if (array_key_exists('headers', $options)) {
            if($options['headers']===false){ //no headers
                unset($view->vars['headers']);
            }else if (is_array($options['headers'])){ //headers passed in
                $view->vars['headers'] = $options['headers'];
            }
        }else { //harvest labels from  collection elements
            $elementtype = $form->getConfig()->getOption('type');

            //should be a guard clause here so types that won't supply good headers (e.g. a collection of text fields) will skip the rest

            $element = $form->getConfig()->getFormFactory()->create($elementtype); //get dummy instance of collection element
            $fields = $element->all(); 
            $headers = array();
            foreach($fields as $field){
                $label= $field->getConfig()->getOption('label');
                $headers[] = empty($label) ? $field->getName() : $label;
            }
            $view->vars['headers'] = $headers;

        }
    }
}

如果有人使用更干净的方法,我会全力以赴。