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



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

例如

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

因此,如果我的DoofusType有一个FooTypes的集合,

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

应该导致一个视图,其中集合的标题将是Foo、Bar和Fibble,或者FooType的标签属性的值(如果设置了它们)。

这是我的collection分机:

<?php
namespace ACCMainBundleForm;
use SymfonyComponentFormAbstractTypeExtension;
use SymfonyComponentFormFormView;
use SymfonyComponentFormFormInterface;
use SymfonyComponentPropertyAccessPropertyAccess;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
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();
}

但如果集合是空的,那也无济于事。如果集合元素类型已经定义了标签,这也没有帮助。有什么想法吗?

经过对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;
}
}
}

如果有人有更清洁的方法,我洗耳恭听。

最新更新