Symfony 2.7 表单实体类型在表单中呈现多个属性
Symfony 2.7 Form Entity type render multiple properties in form
我以前有这个工作,但它停止使用 Symfony 2.7
我想要的是呈现一个 expanded/multiple 实体选择列表,以便我显示多个自定义属性。目标是将选项列为:
{name} - {description} More info
所以我创建了一个以 "entity" 作为父级的自定义表单类型,这样我就可以自定义表单呈现方式
<?php
namespace Study\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ScholarshipEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setAttribute('dataType', $options['dataType']);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'required' => false,
'dataType' => 'entity'
));
}
public function getAllowedOptionValues(array $options)
{
return array('required' => array(false));
}
public function getParent()
{
return 'entity';
}
public function getName()
{
return 'scholarship_entity';
}
}
我按如下方式呈现类型(它只是基于 Twitter Bootstrap 包模板):
{% block scholarship_entity_widget %}
{% spaceless %}
{% if expanded %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default(''))}) %}
{% set label_attr = label_attr|merge({'class': (label_attr.class ~ ' ' ~ (widget_type != '' ? (multiple ? 'checkbox' : 'radio') ~ '-' ~ widget_type : ''))}) %}
{% if expanded %}
{% set attr = attr|merge({'class': attr.class|default(horizontal_input_wrapper_class)}) %}
{% endif %}
{% for child in form %}
{% if widget_type != 'inline' %}
<div class="{{ multiple ? 'checkbox' : 'radio' }}">
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ form_widget(child, {'horizontal_label_class': horizontal_label_class, 'horizontal_input_wrapper_class': horizontal_input_wrapper_class, 'attr': {'class': attr.widget_class|default('')}}) }}
{{ child.vars.label.name|trans({}, translation_domain) }}
- {{ child.vars.label.description }}
<a href="{{ child.vars.label.link }}" target="_blank">More Information</a>
</label>
{% if widget_type != 'inline' %}
</div>
{% endif %}
{% endfor %}
{{ block('form_message') }}
{% if expanded %}
{% endif %}
{% else %}
{# not being used, just default #}
{{ block('choice_widget_collapsed') }}
{% endif %}
{% endspaceless %}
{% endblock %}
最后,我以另一种形式使用我的自定义类型:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('scholarships', new ScholarshipEntityType(), array(
'class' => 'StudyMainBundle:Scholarship',
'query_builder' => function(EntityRepository $er) use ($options) {
return $er->findAllByOfferingQueryBuilder($options['offering']);
},
'choice_label' => 'entity',
'multiple' => true,
'expanded' => true,
'label' => 'financial.scholarships'
))
;
}
我正在渲染的 "property" 只是实体本身:
/**
* Scholarship
*
* @ORM\Table(name="scholarship")
* @ORM\Entity(repositoryClass="Study\MainBundle\Repository\ScholarshipRepository")
*/
class Scholarship
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
/**
* Get the Entity object for form rendering
*
* @return \Study\MainBundle\Entity\Scholarship
*/
public function getEntity()
{
return $this;
}
}
不幸的是,我将整个实体传递给 Twig 并让我访问属性的技巧似乎不再有效。标签呈现为字符串的地方有一些变化(如果重要的话,我将上面的 'property' 更改为 'choice_label' 2.7)。
错误:
Catchable Fatal Error: Object of class Study\MainBundle\Entity\Scholarship could not be converted to string
堆栈跟踪:
1. in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 251 +
2. at ErrorHandler ->handleError ('4096', 'Object of class Study\MainBundle\Entity\Scholarship could not be converted to string', '/var/project/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php', '251', array('choice' => object(Scholarship), 'key' => '0', 'label' => object(Closure), 'values' => array('2'), 'index' => array('Symfony\Bridge\Doctrine\Form\Type\DoctrineType', 'createChoiceName'), 'attr' => null, 'isPreferred' => array(), 'preferredViews' => array(), 'otherViews' => array(), 'value' => '2', 'nextIndex' => '2'))
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 251 +
3. at DefaultChoiceListFactory ::addChoiceView (object(Scholarship), '0', object(Closure), array('2'), array('Symfony\Bridge\Doctrine\Form\Type\DoctrineType', 'createChoiceName'), null, array(), array(), array())
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 185
还有其他方法吗?
我在考虑以下问题(但不知道具体怎么做或者是否值得研究其中的任何一个):
- 变形金刚
- 派生自 Choice 并执行我想要的自定义类型(可能来自捆绑包)
- 以某种方式使用选择列表工厂
- 将实体作为一些附加字段而不是标签传递(也许是新的 'choice_attr'?)
如果我对问题的理解正确,你应该在你的实体中实现 __toString()
函数,这将格式化你想要在实体的选择列表中打印的字符串。
例如:
function __toString() {
return sprintf("%s - %s", $this->type, $this->description);
}
尝试使用方法AbstractType::buildView(FormView, FormInterface, array)
。您可以在那里访问传递给模板的变量。
我用它来 DaterangeType
为两个日期字段声明单独的 ID 和名称:
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['full_name_0'] = $view->vars['full_name'] . '[0]';
$view->vars['full_name_1'] = $view->vars['full_name'] . '[1]';
$view->vars['id_0'] = $view->vars['id'] . '_0';
$view->vars['id_1'] = $view->vars['id'] . '_1';
}
然后您可以将这些值作为标准 twig 变量访问。
我以前有这个工作,但它停止使用 Symfony 2.7
我想要的是呈现一个 expanded/multiple 实体选择列表,以便我显示多个自定义属性。目标是将选项列为:
{name} - {description} More info
所以我创建了一个以 "entity" 作为父级的自定义表单类型,这样我就可以自定义表单呈现方式
<?php
namespace Study\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ScholarshipEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setAttribute('dataType', $options['dataType']);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'required' => false,
'dataType' => 'entity'
));
}
public function getAllowedOptionValues(array $options)
{
return array('required' => array(false));
}
public function getParent()
{
return 'entity';
}
public function getName()
{
return 'scholarship_entity';
}
}
我按如下方式呈现类型(它只是基于 Twitter Bootstrap 包模板):
{% block scholarship_entity_widget %}
{% spaceless %}
{% if expanded %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default(''))}) %}
{% set label_attr = label_attr|merge({'class': (label_attr.class ~ ' ' ~ (widget_type != '' ? (multiple ? 'checkbox' : 'radio') ~ '-' ~ widget_type : ''))}) %}
{% if expanded %}
{% set attr = attr|merge({'class': attr.class|default(horizontal_input_wrapper_class)}) %}
{% endif %}
{% for child in form %}
{% if widget_type != 'inline' %}
<div class="{{ multiple ? 'checkbox' : 'radio' }}">
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ form_widget(child, {'horizontal_label_class': horizontal_label_class, 'horizontal_input_wrapper_class': horizontal_input_wrapper_class, 'attr': {'class': attr.widget_class|default('')}}) }}
{{ child.vars.label.name|trans({}, translation_domain) }}
- {{ child.vars.label.description }}
<a href="{{ child.vars.label.link }}" target="_blank">More Information</a>
</label>
{% if widget_type != 'inline' %}
</div>
{% endif %}
{% endfor %}
{{ block('form_message') }}
{% if expanded %}
{% endif %}
{% else %}
{# not being used, just default #}
{{ block('choice_widget_collapsed') }}
{% endif %}
{% endspaceless %}
{% endblock %}
最后,我以另一种形式使用我的自定义类型:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('scholarships', new ScholarshipEntityType(), array(
'class' => 'StudyMainBundle:Scholarship',
'query_builder' => function(EntityRepository $er) use ($options) {
return $er->findAllByOfferingQueryBuilder($options['offering']);
},
'choice_label' => 'entity',
'multiple' => true,
'expanded' => true,
'label' => 'financial.scholarships'
))
;
}
我正在渲染的 "property" 只是实体本身:
/**
* Scholarship
*
* @ORM\Table(name="scholarship")
* @ORM\Entity(repositoryClass="Study\MainBundle\Repository\ScholarshipRepository")
*/
class Scholarship
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
/**
* Get the Entity object for form rendering
*
* @return \Study\MainBundle\Entity\Scholarship
*/
public function getEntity()
{
return $this;
}
}
不幸的是,我将整个实体传递给 Twig 并让我访问属性的技巧似乎不再有效。标签呈现为字符串的地方有一些变化(如果重要的话,我将上面的 'property' 更改为 'choice_label' 2.7)。
错误:
Catchable Fatal Error: Object of class Study\MainBundle\Entity\Scholarship could not be converted to string
堆栈跟踪:
1. in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 251 +
2. at ErrorHandler ->handleError ('4096', 'Object of class Study\MainBundle\Entity\Scholarship could not be converted to string', '/var/project/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php', '251', array('choice' => object(Scholarship), 'key' => '0', 'label' => object(Closure), 'values' => array('2'), 'index' => array('Symfony\Bridge\Doctrine\Form\Type\DoctrineType', 'createChoiceName'), 'attr' => null, 'isPreferred' => array(), 'preferredViews' => array(), 'otherViews' => array(), 'value' => '2', 'nextIndex' => '2'))
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 251 +
3. at DefaultChoiceListFactory ::addChoiceView (object(Scholarship), '0', object(Closure), array('2'), array('Symfony\Bridge\Doctrine\Form\Type\DoctrineType', 'createChoiceName'), null, array(), array(), array())
in vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php at line 185
还有其他方法吗?
我在考虑以下问题(但不知道具体怎么做或者是否值得研究其中的任何一个):
- 变形金刚
- 派生自 Choice 并执行我想要的自定义类型(可能来自捆绑包)
- 以某种方式使用选择列表工厂
- 将实体作为一些附加字段而不是标签传递(也许是新的 'choice_attr'?)
如果我对问题的理解正确,你应该在你的实体中实现 __toString()
函数,这将格式化你想要在实体的选择列表中打印的字符串。
例如:
function __toString() {
return sprintf("%s - %s", $this->type, $this->description);
}
尝试使用方法AbstractType::buildView(FormView, FormInterface, array)
。您可以在那里访问传递给模板的变量。
我用它来 DaterangeType
为两个日期字段声明单独的 ID 和名称:
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['full_name_0'] = $view->vars['full_name'] . '[0]';
$view->vars['full_name_1'] = $view->vars['full_name'] . '[1]';
$view->vars['id_0'] = $view->vars['id'] . '_0';
$view->vars['id_1'] = $view->vars['id'] . '_1';
}
然后您可以将这些值作为标准 twig 变量访问。