我确信我理解这个过程,但是当我深入挖掘时,我发现我错了;(
我们采用简单的形式,请注意此表单包含3个字段
$form = $this->createFormBuilder($defaultData, ['csrf_protection' => false])
->add('email', 'email')
->add('name', 'text')
->add('message', 'textarea')
->getForm()
->createView();
呈现为
{{ form(form, {'attr': {'novalidate': 'novalidate'}}) }}
进入
来自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次? 或者说其他方式如何呈现电子邮件和消息?
答案 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 (基本默认行)。将呈现表单主题中定义的第一个块。
块本身的定义发生在主题文件中。