【问题标题】:Symfony 2.7 Form Entity type render multiple properties in formSymfony 2.7 表单实体类型在表单中呈现多个属性
【发布时间】:2015-11-28 20:20:19
【问题描述】:

我之前有这个工作,但它在 Symfony 2.7 中停止工作

我想要的是呈现一个扩展/多个实体选择列表,以便我显示多个自定义属性。目标是将选项列出为:

{name} - {description} 更多信息

所以我创建了一个以“实体”为父的自定义表单类型,这样我就可以自定义表单呈现

<?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'
        ))
    ;
}

我正在渲染的“属性”只是实体本身:

/**
 * 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 并让我访问属性的技巧不再有效。将标签呈现为字符串的地方有一些变化(我在 2.7 上将 'property' 更改为 'choice_label',如果这很重要的话)。

错误:

可捕获的致命错误:Study\MainBundle\Entity\Scholarship 类的对象无法转换为字符串

堆栈跟踪:

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”?)

【问题讨论】:

  • 由于选择字段获得了heavily changed in 2.7,请尝试其他一些新属性。也许'choices_as_values' =&gt; true 可以解决问题。
  • 我刚刚完成了所有表单的转换。在这种情况下它没有帮助(我认为这不是 2.7 的默认更改,而是 3.0 中的默认更改)
  • 在 2.5 中可以使用字段类型的buildView 方法将任意数据传递给模板。

标签: forms symfony symfony-2.7


【解决方案1】:

如果我对问题的理解正确,您应该在您的实体中实现__toString() 函数,它将格式化您要在实体的选择列表中打印的字符串。

例如:

function __toString() {
  return sprintf("%s - %s", $this->type, $this->description);
}

【讨论】:

  • 我还想在a html 标记内显示一个链接。但是我可以只做所有这些并将标签设置为呈现而不转义 HTML 吗?
  • 这很棘手...在这种情况下,在__toString() 函数中,您可以使用htmlentities($this-&gt;name)htmlEntities($this-&gt;description),加上链接(在&lt;a&gt;&lt;/a&gt; 内),然后使用|raw ...
  • 我使用了htmlspecialchars(显然,这就是 Twig 所做的)。我还将其定义为一个新的吸气剂,只是为了保持清洁。否则,这个解决方案对我有用。我对将代码从 Twig 移动到 Entity 不满意,但它可以工作。
【解决方案2】:

尝试使用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 变量访问。

【讨论】:

  • 这可能会有所帮助。但是如果我有一个“实体”类型,那么选择会根据我运行的查询自动链接到实体。在实体选择类型中是否有某种方法可以针对每个选择执行此操作?
猜你喜欢
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2016-03-20
  • 2018-07-28
相关资源
最近更新 更多