创建一个Html的form标签,当提交数据正确,则返回我们上一节创建的路由和控制器。可以使用最简单的Twig的form_widget函数,一次性渲染完成表单。把form变量传给他,还要添加一个提交按钮:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{# src/Yoda/UserBundle/Resources/views/Register/register.html.twig #} {# ... #} {% block body %} <section class="main-block"> <article> <section> <h1>Register</h1> <form action="{{ path('user_register') }}" method="POST"> {{ form_widget(form) }} <input type="submit" class="btn btn-primary pull-right" value="Register!" /> </form> </section> </article> </section> {% endblock %} |
Form和FormView
刷新页面,有一个错误!
An exception has been thrown during the rendering of a template (“Catchable Fatal Error: Argument 1 passed to SymfonyComponentFormFormRenderer::searchAndRenderBlock() must be an instance of SymfonyComponentFormFormView, instance of SymfonyComponentFormForm given, called in …”)
这一次更难查找,但它却有一个重要的描述:
Argument 1 passed to FormRenderer::searchAndRenderBlock() must be an instance of FormView, instance of Form given
我们调用了一个方法,但给他传入了一个错误的类型。它需要一个FormView,但是我给他传入了一个Fom。让我们回头看看RegisterController。当你传递form给表单,你一定要createView它。这个对象就会从Form类型转变成FormView。
1 2 3 4 5 6 7 8 |
// src/Yoda/UserBundle/Controller/RegisterController.php public function registerAction() { // ... return array('form' => $form->createView()); } |
这个没什么技巧,只要死记硬背即可。虽然不好排查,但是现在你掌握了!
刷新并庆祝一下。实际上,我们还没有编写任何代码来处理表单提交——给我再来一分钟。
form()和button
有一种更加容易的方式来呈现表单,虽然我很不喜欢这样,但还是希望你能够了解。你可以查看Forms Chapter、Rendering the Form。它会让模版渲染表单只需要一行:
1 |
{{ form(form) }} |
如果你配置一下,他会显示这些字段、html的form标签和一个button按钮。如果你向上滚动,你会看到这个form有一个save字段并且他是submit类型:
1 2 3 4 |
$form = $this->createFormBuilder($task) // ... ->add('save', 'submit') ->getForm(); |
它可以只用一行代码渲染html表单和button按钮,你明白了就行。
呈现一个字段
在现实情况下,一次呈现表单不能带来灵活性。你可以使用form_row函数去渲染每一个单独的字段:
1 2 3 4 5 6 7 8 9 10 |
{# src/Yoda/UserBundle/Resources/views/Register/register.html.twig #} {# ... #} <form action="{{ path('user_register') }}" method="POST"> {{ form_row(form.username) }} {{ form_row(form.email) }} {{ form_row(form.password) }} <input type="submit" class="btn btn-primary pull-right" value="Register!" /> </form> |
刷新页面并检查一下表单。每个字段都被一个div围绕并含有label和input:
1 2 3 4 5 |
<div> <label for="form_username" class="required">Username</label> <input type="text" id="form_username" name="form[username]" required="required" /> </div> <!-- ... --> |
使用form_widget、form_label和form_errors
接下来,我们将学会如何定制一个字段的每一个信息。开始使用单独的form_label, form_widget 和 form_errors函数。让我们用username字段试试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{# src/Yoda/UserBundle/Resources/views/Register/register.html.twig #} {# ... #} <form action="{{ path('user_register') }}" method="POST"> <div class="awesome-username-wrapper"> {{ form_errors(form.username) }} {{ form_label(form.username) }} {{ form_widget(form.username) }} </div> {{ form_row(form.email) }} {{ form_row(form.password) }} <input type="submit" class="btn btn-primary pull-right" value="Register!" /> </form> |
form_row会自动生成这三个部分,所以现在和之前没什么两样。通常只要有可能我就习惯于使用form_row。
不要忘记form_errors和form_rest!
除了字段本身,还应该有两个其他的函数。第一个是整个表单的错误提示form_errors:
1 2 3 4 5 6 7 8 9 10 11 12 |
{# src/Yoda/UserBundle/Resources/views/Register/register.html.twig #} {# ... #} <form action="{{ path('user_register') }}" method="POST"> {{ form_errors(form) }} {{ form_row(form.username) }} {{ form_row(form.email) }} {{ form_row(form.password) }} <input type="submit" class="btn btn-primary pull-right" value="Register!" /> </form> |
字段的错误会显示在字段旁。但是在某些情况下,您可能有一个“全局”的错误,并不适用于任何一个特定的领域。这不是很常见,但还是要呈现这些。
下一步,添加form_rest。他会渲染你忘记的字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{# src/Yoda/UserBundle/Resources/views/Register/register.html.twig #} {# ... #} <form action="{{ path('user_register') }}" method="POST"> {{ form_errors(form) }} {{ form_row(form.username) }} {{ form_row(form.email) }} {{ form_row(form.password) }} {{ form_rest(form) }} <input type="submit" class="btn btn-primary pull-right" value="Register!" /> </form> |
除此之外,form_rest是他非常的方便,因为他会自动渲染一些隐藏字段。
默认情况下,所有form都有一个隐藏的“token” ,以防止csrf攻击。只要有form_rest,我们就永远不用担心或思考这些隐藏字段。
我很谈论了很多,更多细节我们可以查看symfony官方的一篇文章Twig Template Form Function and Variable Reference。