@@ -145,35 +145,27 @@ helper functions:
145
145
.. code-block :: html+jinja
146
146
147
147
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #}
148
- <form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}>
149
- {{ form_widget(form) }}
150
-
151
- <input type="submit" />
152
- </form>
148
+ {{ form(form) }}
153
149
154
150
.. code-block :: html+php
155
151
156
152
<!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php -->
157
- <form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view['form']->enctype($form) ?> >
158
- <?php echo $view['form']->widget($form) ?>
159
-
160
- <input type="submit" />
161
- </form>
153
+ <?php echo $view['form']->form($form) ?>
162
154
163
155
.. image :: /images/book/form-simple.png
164
156
:align: center
165
157
166
158
.. note ::
167
159
168
- This example assumes that you've created a route called `` task_new ``
169
- that points to the `` AcmeTaskBundle:Default:new `` controller that
170
- was created earlier .
160
+ This example assumes that you submit the form in a "POST" request and to
161
+ the same URL that it was displayed in. You will learn later how to
162
+ change the request method and the target URL of the form .
171
163
172
- That's it! By printing ``form_widget (form) ``, each field in the form is
173
- rendered, along with a label and error message (if there is one). As easy
174
- as this is, it's not very flexible (yet). Usually, you'll want to render each
175
- form field individually so you can control how the form looks. You'll learn how
176
- to do that in the ":ref: `form-rendering-template `" section.
164
+ That's it! By printing ``form (form) ``, each field in the form is rendered, along
165
+ with a label and error message (if there is one). As easy as this is, it's not
166
+ very flexible (yet). Usually, you'll want to render each form field individually
167
+ so you can control how the form looks. You'll learn how to do that in the
168
+ ":ref: `form-rendering-template `" section.
177
169
178
170
Before moving on, notice how the rendered ``task `` input field has the value
179
171
of the ``task `` property from the ``$task `` object (i.e. "Write a blog post").
@@ -201,7 +193,7 @@ Handling Form Submissions
201
193
202
194
The second job of a form is to translate user-submitted data back to the
203
195
properties of an object. To make this happen, the submitted data from the
204
- user must be bound to the form. Add the following functionality to your
196
+ user must be written into the form. Add the following functionality to your
205
197
controller::
206
198
207
199
// ...
@@ -217,53 +209,54 @@ controller::
217
209
->add('dueDate', 'date')
218
210
->getForm();
219
211
220
- if ($request->isMethod('POST')) {
221
- $form->bind($request);
212
+ $form->handleRequest($request);
222
213
223
- if ($form->isValid()) {
224
- // perform some action, such as saving the task to the database
214
+ if ($form->isValid()) {
215
+ // perform some action, such as saving the task to the database
225
216
226
- return $this->redirect($this->generateUrl('task_success'));
227
- }
217
+ return $this->redirect($this->generateUrl('task_success'));
228
218
}
229
219
230
220
// ...
231
221
}
232
222
233
- .. versionadded :: 2.1
234
- The ``bind `` method was made more flexible in Symfony 2.1. It now accepts
235
- the raw client data (same as before) or a Symfony Request object. This
236
- is preferred over the deprecated ``bindRequest `` method.
237
-
238
- Now, when submitting the form, the controller binds the submitted data to the
239
- form, which translates that data back to the ``task `` and ``dueDate `` properties
240
- of the ``$task `` object. This all happens via the ``bind() `` method.
241
-
242
- .. note ::
243
-
244
- As soon as ``bind() `` is called, the submitted data is transferred
245
- to the underlying object immediately. This happens regardless of whether
246
- or not the underlying data is actually valid.
223
+ .. versionadded :: 2.3
224
+ The :method: `Symfony\C omponent\F orm\F ormInterface::handleRequest ` method was
225
+ added in Symfony 2.3. Before you had to do some manual work to achieve the
226
+ same result.
247
227
248
228
This controller follows a common pattern for handling forms, and has three
249
229
possible paths:
250
230
251
- #. When initially loading the page in a browser, the request method is ``GET ``
252
- and the form is simply created and rendered;
231
+ #. When initially loading the page in a browser, the form is simply created and
232
+ rendered. :method: `Symfony\C omponent\F orm\F ormInterface::handleRequest `
233
+ recognizes that the form was not submitted and does nothing.
234
+ :method: `Symfony\C omponent\F orm\F ormInterface::isValid ` returns ``false ``
235
+ if the form was not submitted.
253
236
254
- #. When the user submits the form (i.e. the method is ``POST ``) with invalid
255
- data (validation is covered in the next section), the form is bound and
256
- then rendered, this time displaying all validation errors;
237
+ #. When the user submits the form, :method: `Symfony\C omponent\F orm\F ormInterface::handleRequest `
238
+ recognizes this and immediately writes the submitted data back into the
239
+ ``task `` and ``dueDate `` properties of the ``$task `` object. Then this object
240
+ is validated. If it is invalid (validation is covered in the next section),
241
+ :method: `Symfony\C omponent\F orm\F ormInterface::isValid ` returns ``false ``
242
+ again, so the form is rendered together with all validation errors;
257
243
258
- #. When the user submits the form with valid data, the form is bound and
259
- you have the opportunity to perform some actions using the ``$task ``
260
- object (e.g. persisting it to the database) before redirecting the user
261
- to some other page (e.g. a "thank you" or "success" page).
244
+ .. note ::
262
245
263
- .. note ::
246
+ You can use the method :method: `Symfony\C omponent\F orm\F ormInterface::isBound `
247
+ to check whether a form was submitted, regardless of whether or not the
248
+ submitted data is actually valid.
249
+
250
+ #. When the user submits the form with valid data, the submitted data is again
251
+ written into the form, but this time :method: `Symfony\C omponent\F orm\F ormInterface::isValid `
252
+ returns ``true ``. Now you have the opportunity to perform some actions using
253
+ the ``$task `` object (e.g. persisting it to the database) before redirecting
254
+ the user to some other page (e.g. a "thank you" or "success" page).
264
255
265
- Redirecting a user after a successful form submission prevents the user
266
- from being able to hit "refresh" and re-post the data.
256
+ .. note ::
257
+
258
+ Redirecting a user after a successful form submission prevents the user
259
+ from being able to hit "refresh" and re-post the data.
267
260
268
261
.. index ::
269
262
single: Forms; Validation
@@ -429,7 +422,7 @@ to an array callback, or a ``Closure``::
429
422
}
430
423
431
424
This will call the static method ``determineValidationGroups() `` on the
432
- ``Client `` class after the form is bound , but before validation is executed.
425
+ ``Client `` class after the form is submitted , but before validation is executed.
433
426
The Form object is passed as an argument to that method (see next example).
434
427
You can also define whole logic inline by using a Closure::
435
428
@@ -605,35 +598,30 @@ of code. Of course, you'll usually need much more flexibility when rendering:
605
598
.. code-block :: html+jinja
606
599
607
600
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #}
608
- <form action=" {{ path('task_new') }}" method="post" {{ form_enctype( form) }}>
601
+ {{ form_start( form) }}
609
602
{{ form_errors(form) }}
610
603
611
604
{{ form_row(form.task) }}
612
605
{{ form_row(form.dueDate) }}
613
606
614
- {{ form_rest(form) }}
615
-
616
607
<input type="submit" />
617
- </ form>
608
+ {{ form_end( form) }}
618
609
619
610
.. code-block :: html+php
620
611
621
612
<!-- src/Acme/TaskBundle/Resources/views/Default/newAction.html.php -->
622
- <form action="< ?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view[' form']->enctype ($form) ?> >
613
+ <?php echo $view['form']->start ($form) ?>
623
614
<?php echo $view['form']->errors($form) ?>
624
615
625
616
<?php echo $view['form']->row($form['task']) ?>
626
617
<?php echo $view['form']->row($form['dueDate']) ?>
627
618
628
- <?php echo $view['form']->rest($form) ?>
629
-
630
619
<input type="submit" />
631
- </ form>
620
+ <?php echo $view[' form']->end($form) ? >
632
621
633
622
Take a look at each part:
634
623
635
- * ``form_enctype(form) `` - If at least one field is a file upload field, this
636
- renders the obligatory ``enctype="multipart/form-data" ``;
624
+ * ``form_start(form) `` - Renders the start tag of the form.
637
625
638
626
* ``form_errors(form) `` - Renders any errors global to the whole form
639
627
(field-specific errors are displayed next to each field);
@@ -642,10 +630,8 @@ Take a look at each part:
642
630
form widget for the given field (e.g. ``dueDate ``) inside, by default, a
643
631
``div `` element;
644
632
645
- * ``form_rest(form) `` - Renders any fields that have not yet been rendered.
646
- It's usually a good idea to place a call to this helper at the bottom of
647
- each form (in case you forgot to output a field or don't want to bother
648
- manually rendering hidden fields). This helper is also useful for taking
633
+ * ``form_end() `` - Renders the end tag of the form and any fields that have not
634
+ yet been rendered. This is useful for rendering hidden fields and taking
649
635
advantage of the automatic :ref: `CSRF Protection<forms-csrf> `.
650
636
651
637
The majority of the work is done by the ``form_row `` helper, which renders
@@ -740,7 +726,7 @@ field:
740
726
741
727
.. code-block :: html+jinja
742
728
743
- {{ form_widget(form.task, { 'attr': {'class': 'task_field'} }) }}
729
+ {{ form_widget(form.task, {'attr': {'class': 'task_field'}}) }}
744
730
745
731
.. code-block :: html+php
746
732
@@ -783,6 +769,75 @@ available in the :doc:`reference manual</reference/forms/twig_reference>`.
783
769
Read this to know everything about the helpers available and the options
784
770
that can be used with each.
785
771
772
+ .. index ::
773
+ single: Forms; Changing the action and method
774
+
775
+ .. _book-forms-changing-action-and-method :
776
+
777
+ Changing the Action and Method of a Form
778
+ ----------------------------------------
779
+
780
+ So far, we have used the ``form_start() `` helper to render the form's start tag
781
+ and assumed that each form is submitted to the same URL in a POST request.
782
+ Sometimes you want to change these parameters. You can do so in a few different
783
+ ways. If you build your form in the controller, you can use ``setAction() `` and
784
+ ``setMethod() ``::
785
+
786
+ $form = $this->createFormBuilder($task)
787
+ ->setAction($this->generateUrl('target_route'))
788
+ ->setMethod('GET')
789
+ ->add('task', 'text')
790
+ ->add('dueDate', 'date')
791
+ ->getForm();
792
+
793
+ .. note ::
794
+
795
+ This example assumes that you've created a route called ``target_route ``
796
+ that points to the controller that processes the form.
797
+
798
+ In :ref: `book-form-creating-form-classes ` you will learn how to outsource the
799
+ form building code into separate classes. When using such a form class in the
800
+ controller, you can pass the action and method as form options::
801
+
802
+ $form = $this->createForm(new TaskType(), $task, array(
803
+ 'action' => $this->generateUrl('target_route'),
804
+ 'method' => 'GET',
805
+ ));
806
+
807
+ At last, you can override the action and method in the template by passing them
808
+ to the ``form() `` or the ``form_start() `` helper:
809
+
810
+ .. configuration-block ::
811
+
812
+ .. code-block :: html+jinja
813
+
814
+ {# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #}
815
+ {{ form(form, {'action': path('target_route'), 'method': 'GET'}) }}
816
+
817
+ {{ form_start(form, {'action': path('target_route'), 'method': 'GET'}) }}
818
+
819
+ .. code-block :: html+php
820
+
821
+ <!-- src/Acme/TaskBundle/Resources/views/Default/newAction.html.php -->
822
+ <?php echo $view['form']->form($form, array(
823
+ 'action' => $view['router']->generate('target_route'),
824
+ 'method' => 'GET',
825
+ )) ?>
826
+
827
+ <?php echo $view['form']->start($form, array(
828
+ 'action' => $view['router']->generate('target_route'),
829
+ 'method' => 'GET',
830
+ )) ?>
831
+
832
+ .. note ::
833
+
834
+ If the form's method is not GET or POST, but PUT, PATCH or DELETE, Symfony2
835
+ will insert a hidden field with the name "_method" that stores this method.
836
+ The form will be submitted in a normal POST request, but Symfony2's router
837
+ is capable of detecting the "_method" parameter and will interpret the
838
+ request as PUT, PATCH or DELETE request. Read the cookbook chapter
839
+ ":doc: `/cookbook/routing/method_parameters `" for more information.
840
+
786
841
.. index ::
787
842
single: Forms; Creating form classes
788
843
@@ -912,7 +967,7 @@ you can fetch it from the form::
912
967
913
968
For more information, see the :doc: `Doctrine ORM chapter</book/doctrine> `.
914
969
915
- The key thing to understand is that when the form is bound , the submitted
970
+ The key thing to understand is that when the form is submitted , the submitted
916
971
data is transferred to the underlying object immediately. If you want to
917
972
persist that data, you simply need to persist the object itself (which already
918
973
contains the submitted data).
@@ -1143,7 +1198,7 @@ renders the form:
1143
1198
1144
1199
{% form_theme form 'AcmeTaskBundle:Form: fields.html.twig' 'AcmeTaskBundle:Form: fields2.html.twig' %}
1145
1200
1146
- < form ...>
1201
+ {{ form(form) }}
1147
1202
1148
1203
.. code-block :: html+php
1149
1204
@@ -1152,7 +1207,7 @@ renders the form:
1152
1207
1153
1208
<?php $view['form']->setTheme($form, array('AcmeTaskBundle:Form', 'AcmeTaskBundle:Form')) ?>
1154
1209
1155
- <form ... >
1210
+ <?php echo $view[' form']->form($form) ? >
1156
1211
1157
1212
The ``form_theme `` tag (in Twig) "imports" the fragments defined in the given
1158
1213
template and uses them when rendering the form. In other words, when the
@@ -1231,7 +1286,7 @@ are 4 possible *parts* of a form that can be rendered:
1231
1286
1232
1287
.. note ::
1233
1288
1234
- There are actually 3 other *parts * - ``rows ``, `` rest ``, and ``enctype `` -
1289
+ There are actually 2 other *parts * - ``rows `` and ``rest `` -
1235
1290
but you should rarely if ever need to worry about overriding them.
1236
1291
1237
1292
By knowing the field type (e.g. ``textarea ``) and which part you want to
@@ -1486,12 +1541,12 @@ an array of the submitted data. This is actually really easy::
1486
1541
->add('message', 'textarea')
1487
1542
->getForm();
1488
1543
1489
- if ($request->isMethod('POST')) {
1490
- $form->bind($request);
1544
+ $form->handleRequest($request);
1491
1545
1492
- // data is an array with "name", "email", and "message" keys
1493
- $data = $form->getData();
1494
- }
1546
+ if ($form->isBound()) {
1547
+ // data is an array with "name", "email", and "message" keys
1548
+ $data = $form->getData();
1549
+ }
1495
1550
1496
1551
// ... render the form
1497
1552
}
@@ -1526,15 +1581,15 @@ Adding Validation
1526
1581
1527
1582
The only missing piece is validation. Usually, when you call ``$form->isValid() ``,
1528
1583
the object is validated by reading the constraints that you applied to that
1529
- class. If your form is binding to an object (i.e. you're using the ``data_class ``
1584
+ class. If your form is mapped to an object (i.e. you're using the ``data_class ``
1530
1585
option or passing an object to your form), this is almost always the approach
1531
1586
you want to use. See :doc: `/book/validation ` for more details.
1532
1587
1533
1588
.. _form-option-constraints :
1534
1589
1535
- But if you're not binding to an object and are instead retrieving a simple
1536
- array of your submitted data, how can you add constraints to the data of your
1537
- form?
1590
+ But if the form is not mapped to an object and you instead want to retrieve a
1591
+ simple array of your submitted data, how can you add constraints to the data of
1592
+ your form?
1538
1593
1539
1594
The answer is to setup the constraints yourself, and attach them to the individual
1540
1595
fields. The overall approach is covered a bit more in the :ref: `validation chapter<book-validation-raw-values> `,
0 commit comments