symfony表单是如何在视图中呈现的

时间:2014-03-06 15:58:02

标签: forms symfony twig

我确信我理解这个过程,但是当我深入挖掘时,我发现我错了;(

我们采用简单的形式,请注意此表单包含3个字段

    $form = $this->createFormBuilder($defaultData, ['csrf_protection' => false])
            ->add('email', 'email')
            ->add('name', 'text')
            ->add('message', 'textarea')
            ->getForm()
            ->createView();

呈现为

{{ form(form, {'attr': {'novalidate': 'novalidate'}}) }}

进入

enter image description here

来自vendor \ symfony \ symfony \ src \ Symfony \ Bridge \ Twig \ Resources \ views \ Form \ form_div_layout.html.twig的“form”块内置如下:

{% block form %}
{% spaceless %}
    {{ form_start(form) }}
        {{ form_widget(form) }}
    {{ form_end(form) }}
{% endspaceless %}
{% endblock form %}

和form_widget(form)

{% block form_widget %}
{% spaceless %}
    {% if compound %}
        {{ block('form_widget_compound') }}
    {% else %}
        {{ block('form_widget_simple') }}
    {% endif %}
{% endspaceless %}
{% endblock form_widget %}

{% block form_widget_simple %}
{% spaceless %}
    {% set type = type|default('text') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock form_widget_simple %}

让我们稍微修改一下form和form_widget:

{% block form %}
{% spaceless %}
    {{ form_start(form) }}
        -form_widget before-
        {{ form_widget(form) }}
        -form_widget after-
    {{ form_end(form) }}
{% endspaceless %}
{% endblock form %}

{% block form_widget %}
{% spaceless %}
    - form_widget call -
    {% if compound %}
        - form_widget compound-
        {{ block('form_widget_compound') }}
    {% else %}
        - form_widget simple-
        {{ block('form_widget_simple') }}
    {% endif %}
{% endspaceless %}
{% endblock form_widget %}

然后作为我得到的输出(列表5):

<form name="form" method="post" action="" novalidate="novalidate">
    -form_widget before-
    - form_widget call -
    - form_widget compound-
    <div id="form" novalidate="novalidate">
        <div>
            <label for="form_email" class="required">Email</label>
            <input type="email" id="form_email" name="form[email]" required="required" />
        </div>
        <div>
            <label for="form_name" class="required">Name</label>
            - form_widget call -
            - form_widget simple-
            <input type="text" id="form_name" name="form[name]" required="required" />
        </div>
        <div>
            <label for="form_message" class="required">Message</label>
            <textarea id="form_message" name="form[message]" required="required">Type your message here</textarea>
        </div>
    </div>
    -form_widget after-
</form>

我们可以很容易地忽略流程

表格 - &gt; form_widget(输入参数是整个表单) - &gt; form_widget_compound - &gt; form_rows(将表单元素迭代到下一个函数中) - &gt; form_row - &gt; form_widget(此调用表单元素作为参数传递)

所以这里是问题的时间,如果form_widget被调用4次(或更多),一次用于表单,3次用于字段那么为什么在列表5'form_widget调用'文本只出现2次? 或者说其他方式如何呈现电子邮件和消息?

1 个答案:

答案 0 :(得分:4)

SF2中的表单主题使用继承。这意味着如果定义了名为 email_widget textarea_widget 的块,则电子邮件 textarea 字段都不会使用 form_widget 。他们宁愿分别使用自己的小部件块: email_widget textarea_widget

好吧,在 form_div_layout.twig 中,定义了这两个小部件块。因此,不会为您的2个字段调用 form_widget 。因此,您的消息显示2次而不是4次。

如果要自定义这些字段的呈现,则必须在自定义表单主题文件中创建自己的块定义 email_widget textarea_widget

修改

默认表单主题文件在 Symfony \ Bridge \ Twig \ Resources \ views \ Form 下定义。使用的默认文件是 form_div_layout.html.twig

虽然继承逻辑本身确实在TWIG桥的PHP代码中,但它没有定义从哪个块继承哪个块。

继承实际上是在 FormType 类中定义的。每个表单类型类都有一个 getParent()方法,该方法返回它继承的表单的名称。表单类型的名称是其关联表单类型类的方法 getName()的结果。例如,使用内置示例, Symfony \ Component \ Form \ Extension \ Core \ Type \ TextareaType

Textarea&gt;&gt;文字&gt;&gt;字段&gt;&gt;表格

您所要做的就是寻找方法 getParent() getName()。因此,默认情况下,在渲染textarea行时,Twig将搜索块 textarea_row text_row field_row ,最后 form_row (基本默认行)。将呈现表单主题中定义的第一个块。

块本身的定义发生在主题文件中。