Skip to content

Added information about the new form(), form_start() and form_end() helpers #2092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 21, 2013
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Documented the usage of FormInterface::handleRequest
  • Loading branch information
webmozart committed Apr 20, 2013
commit 07639000021b44b2a4b3085280bc91ebbd2964e4
5 changes: 3 additions & 2 deletions book/controller.rst
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ working with forms, for example::
{
$form = $this->createForm(...);

$form->bind($request);
$form->handleRequest($request);
// ...
}

Expand Down Expand Up @@ -663,7 +663,8 @@ For example, imagine you're processing a form submit::
{
$form = $this->createForm(...);

$form->bind($this->getRequest());
$form->handleRequest($this->getRequest());

if ($form->isValid()) {
// do some sort of processing

Expand Down
89 changes: 45 additions & 44 deletions book/forms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Handling Form Submissions

The second job of a form is to translate user-submitted data back to the
properties of an object. To make this happen, the submitted data from the
user must be bound to the form. Add the following functionality to your
user must be written into the form. Add the following functionality to your
controller::

// ...
Expand All @@ -209,53 +209,54 @@ controller::
->add('dueDate', 'date')
->getForm();

if ($request->isMethod('POST')) {
$form->bind($request);
$form->handleRequest($request);

if ($form->isValid()) {
// perform some action, such as saving the task to the database
if ($form->isValid()) {
// perform some action, such as saving the task to the database

return $this->redirect($this->generateUrl('task_success'));
}
return $this->redirect($this->generateUrl('task_success'));
}

// ...
}

.. versionadded:: 2.1
The ``bind`` method was made more flexible in Symfony 2.1. It now accepts
the raw client data (same as before) or a Symfony Request object. This
is preferred over the deprecated ``bindRequest`` method.

Now, when submitting the form, the controller binds the submitted data to the
form, which translates that data back to the ``task`` and ``dueDate`` properties
of the ``$task`` object. This all happens via the ``bind()`` method.

.. note::

As soon as ``bind()`` is called, the submitted data is transferred
to the underlying object immediately. This happens regardless of whether
or not the underlying data is actually valid.
.. versionadded:: 2.3
The :method:`Symfony\Component\Form\FormInterface::handleRequest` method was
added in Symfony 2.3. Before you had to do some manual work to achieve the
same result.

This controller follows a common pattern for handling forms, and has three
possible paths:

#. When initially loading the page in a browser, the request method is ``GET``
and the form is simply created and rendered;
#. When initially loading the page in a browser, the form is simply created and
rendered. :method:`Symfony\Component\Form\FormInterface::handleRequest`
recognizes that the form was not submitted and does nothing.
:method:`Symfony\Component\Form\FormInterface::isValid` returns ``false``
if the form was not submitted.

#. When the user submits the form (i.e. the method is ``POST``) with invalid
data (validation is covered in the next section), the form is bound and
then rendered, this time displaying all validation errors;
#. When the user submits the form, :method:`Symfony\Component\Form\FormInterface::handleRequest`
recognizes this and immediately writes the submitted data back into the
``task`` and ``dueDate`` properties of the ``$task`` object. Then this object
is validated. If it is invalid (validation is covered in the next section),
:method:`Symfony\Component\Form\FormInterface::isValid` returns ``false``
again, so the form is rendered together with all validation errors;

#. When the user submits the form with valid data, the form is bound and
you have the opportunity to perform some actions using the ``$task``
object (e.g. persisting it to the database) before redirecting the user
to some other page (e.g. a "thank you" or "success" page).
.. note::

.. note::
You can use the method :method:`Symfony\Component\Form\FormInterface::isBound`
to check whether a form was submitted, regardless of whether or not the
submitted data is actually valid.

#. When the user submits the form with valid data, the submitted data is again
written into the form, but this time :method:`Symfony\Component\Form\FormInterface::isValid`
returns ``true``. Now you have the opportunity to perform some actions using
the ``$task`` object (e.g. persisting it to the database) before redirecting
the user to some other page (e.g. a "thank you" or "success" page).

.. note::

Redirecting a user after a successful form submission prevents the user
from being able to hit "refresh" and re-post the data.
Redirecting a user after a successful form submission prevents the user
from being able to hit "refresh" and re-post the data.

.. index::
single: Forms; Validation
Expand Down Expand Up @@ -421,7 +422,7 @@ to an array callback, or a ``Closure``::
}

This will call the static method ``determineValidationGroups()`` on the
``Client`` class after the form is bound, but before validation is executed.
``Client`` class after the form is submitted, but before validation is executed.
The Form object is passed as an argument to that method (see next example).
You can also define whole logic inline by using a Closure::

Expand Down Expand Up @@ -966,7 +967,7 @@ you can fetch it from the form::

For more information, see the :doc:`Doctrine ORM chapter</book/doctrine>`.

The key thing to understand is that when the form is bound, the submitted
The key thing to understand is that when the form is submitted, the submitted
data is transferred to the underlying object immediately. If you want to
persist that data, you simply need to persist the object itself (which already
contains the submitted data).
Expand Down Expand Up @@ -1540,12 +1541,12 @@ an array of the submitted data. This is actually really easy::
->add('message', 'textarea')
->getForm();

if ($request->isMethod('POST')) {
$form->bind($request);
$form->handleRequest($request);

// data is an array with "name", "email", and "message" keys
$data = $form->getData();
}
if ($form->isBound()) {
// data is an array with "name", "email", and "message" keys
$data = $form->getData();
}

// ... render the form
}
Expand Down Expand Up @@ -1580,15 +1581,15 @@ Adding Validation

The only missing piece is validation. Usually, when you call ``$form->isValid()``,
the object is validated by reading the constraints that you applied to that
class. If your form is binding to an object (i.e. you're using the ``data_class``
class. If your form is mapped to an object (i.e. you're using the ``data_class``
option or passing an object to your form), this is almost always the approach
you want to use. See :doc:`/book/validation` for more details.

.. _form-option-constraints:

But if you're not binding to an object and are instead retrieving a simple
array of your submitted data, how can you add constraints to the data of your
form?
But if the form is not mapped to an object and you instead want to retrieve a
simple array of your submitted data, how can you add constraints to the data of
your form?

The answer is to setup the constraints yourself, and attach them to the individual
fields. The overall approach is covered a bit more in the :ref:`validation chapter<book-validation-raw-values>`,
Expand Down
10 changes: 4 additions & 6 deletions book/validation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,12 @@ workflow looks like the following from inside a controller::
$author = new Author();
$form = $this->createForm(new AuthorType(), $author);

if ($request->isMethod('POST')) {
$form->bind($request);
$form->handleRequest($request);

if ($form->isValid()) {
// the validation passed, do something with the $author object
if ($form->isValid()) {
// the validation passed, do something with the $author object

return $this->redirect($this->generateUrl(...));
}
return $this->redirect($this->generateUrl(...));
}

return $this->render('BlogBundle:Author:form.html.twig', array(
Expand Down
20 changes: 9 additions & 11 deletions cookbook/doctrine/file_uploads.rst
Original file line number Diff line number Diff line change
Expand Up @@ -227,25 +227,23 @@ The following controller shows you how to handle the entire process::
/**
* @Template()
*/
public function uploadAction()
public function uploadAction(Request $request)
{
$document = new Document();
$form = $this->createFormBuilder($document)
->add('name')
->add('file')
->getForm()
;
->getForm();

if ($this->getRequest()->isMethod('POST')) {
$form->bind($this->getRequest());
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$form->handleRequest($request);

$em->persist($document);
$em->flush();
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();

return $this->redirect($this->generateUrl(...));
}
$em->persist($document);
$em->flush();

return $this->redirect($this->generateUrl(...));
}

return array('form' => $form->createView());
Expand Down
4 changes: 2 additions & 2 deletions cookbook/doctrine/registration_form.rst
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,13 @@ and its template:
Finally, create the controller which handles the form submission. This performs
the validation and saves the data into the database::

public function createAction()
public function createAction(Request $request)
{
$em = $this->getDoctrine()->getEntityManager();

$form = $this->createForm(new RegistrationType(), new Registration());

$form->bind($this->getRequest());
$form->handleRequest($request);

if ($form->isValid()) {
$registration = $form->getData();
Expand Down
56 changes: 26 additions & 30 deletions cookbook/form/form_collections.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,10 @@ In your controller, you'll now initialize a new instance of ``TaskType``::

$form = $this->createForm(new TaskType(), $task);

// process the form on POST
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
// ... maybe do some form processing, like saving the Task and Tag objects
}
$form->handleRequest($request);

if ($form->isValid()) {
// ... maybe do some form processing, like saving the Task and Tag objects
}

return $this->render('AcmeTaskBundle:Task:new.html.twig', array(
Expand Down Expand Up @@ -642,40 +640,38 @@ the relationship between the removed ``Tag`` and ``Task`` object.

$editForm = $this->createForm(new TaskType(), $task);

if ($request->isMethod('POST')) {
$editForm->bind($this->getRequest());
$editForm->handleRequest($request);

if ($editForm->isValid()) {
if ($editForm->isValid()) {

// filter $originalTags to contain tags no longer present
foreach ($task->getTags() as $tag) {
foreach ($originalTags as $key => $toDel) {
if ($toDel->getId() === $tag->getId()) {
unset($originalTags[$key]);
}
// filter $originalTags to contain tags no longer present
foreach ($task->getTags() as $tag) {
foreach ($originalTags as $key => $toDel) {
if ($toDel->getId() === $tag->getId()) {
unset($originalTags[$key]);
}
}
}

// remove the relationship between the tag and the Task
foreach ($originalTags as $tag) {
// remove the Task from the Tag
$tag->getTasks()->removeElement($task);
// remove the relationship between the tag and the Task
foreach ($originalTags as $tag) {
// remove the Task from the Tag
$tag->getTasks()->removeElement($task);

// if it were a ManyToOne relationship, remove the relationship like this
// $tag->setTask(null);
// if it were a ManyToOne relationship, remove the relationship like this
// $tag->setTask(null);

$em->persist($tag);
$em->persist($tag);

// if you wanted to delete the Tag entirely, you can also do that
// $em->remove($tag);
}
// if you wanted to delete the Tag entirely, you can also do that
// $em->remove($tag);
}

$em->persist($task);
$em->flush();
$em->persist($task);
$em->flush();

// redirect back to some edit page
return $this->redirect($this->generateUrl('task_edit', array('id' => $id)));
}
// redirect back to some edit page
return $this->redirect($this->generateUrl('task_edit', array('id' => $id)));
}

// render some form template
Expand Down