我已使用collection
扩展了CollectionTableExtension
表单字段类型。我正在尝试设置变量FormView::$vars['headers']
,以便在collection
为is_table
并且没有用户定义的标头可用时,可以使用默认标头输出true
。默认标题应与通常应用于集合成员的标签相同。
e.g。
如果FooType
有3个字段foo
,bar
和fibble
,则其标签将为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();
}
但如果集合为空,则无效。如果集合元素类型已定义标签,则无效。有什么想法吗?
答案 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;
}
}
}
如果有人使用更干净的方法,我会全力以赴。