Skip to content

Commit 243c069

Browse files
committed
[book][form] Adding section about using forms without a class backing the form
1 parent 98c17b8 commit 243c069

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

book/forms.rst

+113
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,8 @@ Placing the form logic into its own class means that the form can be easily
746746
reused elsewhere in your project. This is the best way to create forms, but
747747
the choice is ultimately up to you.
748748

749+
.. _book-forms-data-class:
750+
749751
.. sidebar:: Setting the ``data_class``
750752

751753
Every form needs to know the name of the class that holds the underlying
@@ -1295,6 +1297,117 @@ section.
12951297
The ``intention`` option is optional but greatly enhances the security of
12961298
the generated token by making it different for each form.
12971299

1300+
.. index:
1301+
single: Forms; With no class
1302+
1303+
Using a Form without a Class
1304+
----------------------------
1305+
1306+
In most cases, a form is tied to an object, and the fields of the form get
1307+
and store their data on the properties of that object. This is exactly what
1308+
you've seen so far in this chapter with the `Task` class.
1309+
1310+
But sometimes, you may just want to use a form without a class, and get back
1311+
an array of the submitted data. This is actually really easy::
1312+
1313+
// make sure you've imported the Request namespace above the class
1314+
use Symfony\Component\HttpFoundation\Request
1315+
// ...
1316+
1317+
public function contactAction(Request $request)
1318+
{
1319+
$defaultData = array('message' => 'Type your message here');
1320+
$form = $this->createFormBuilder($defaultData)
1321+
->add('name', 'text')
1322+
->add('email', 'email')
1323+
->add('message', 'textarea')
1324+
->getForm();
1325+
1326+
if ($request->getMethod() == 'POST') {
1327+
$form->bindRequest($request);
1328+
1329+
// data is an array with "name", "email", and "message" keys
1330+
$data = $form->getData();
1331+
}
1332+
1333+
// ... render the form
1334+
}
1335+
1336+
By default, a form actually assumes that you want to work with arrays of
1337+
data, instead of an object. There are exactly two ways that you can change
1338+
this behavior and tie the form to an object instead:
1339+
1340+
1. Pass an object when creating the form (as the first argument to ``createFormBuilder``
1341+
or the second argument to ``createForm``);
1342+
1343+
2. Declare the ``data_class`` option on your form.
1344+
1345+
If you *don't* do either of these, then the form will return the data as
1346+
an array. In this example, since ``$defaultData`` is not an object (and
1347+
no ``data_class`` option is set), ``$form->getData()`` ultimately returns
1348+
an array.
1349+
1350+
Adding Validation
1351+
~~~~~~~~~~~~~~~~~
1352+
1353+
The only missing piece is validation. Usually, when you call ``$form->isValid()``,
1354+
the object is validated by reading the constraints that you applied to that
1355+
class. But without a class, how can you add constraints to the data of your
1356+
form?
1357+
1358+
The answer is to setup the constraints yourself, and pass them into your
1359+
form. The overall approach is covered a bit more in the :ref:`validation chapter<book-validation-raw-values>`,
1360+
but here's a short example::
1361+
1362+
// import the namespaces above your controller class
1363+
use Symfony\Component\Validator\Constraints\Email;
1364+
use Symfony\Component\Validator\Constraints\MinLength;
1365+
use Symfony\Component\Validator\Constraints\Collection;
1366+
1367+
$collectionConstraint = new Collection(array(
1368+
'name' => new MinLength(5)
1369+
'email' => new Email(array('message' => 'Invalid email address')),
1370+
));
1371+
1372+
// create a form, no default values, pass in the constraint option
1373+
$form = $this->createFormBuilder(null, , array(
1374+
'validation_constraint' => $collectionConstraint,
1375+
))->add('email', 'email')
1376+
// ...
1377+
;
1378+
1379+
Now, when you call `$form->isValid()`, the constraints setup here are run
1380+
against your form's data. If you're using a form class, override the ``getDefaultOptions``
1381+
method to specify the option::
1382+
1383+
namespace Acme\TaskBundle\Form\Type;
1384+
1385+
use Symfony\Component\Form\AbstractType;
1386+
use Symfony\Component\Form\FormBuilder;
1387+
use Symfony\Component\Validator\Constraints\Email;
1388+
use Symfony\Component\Validator\Constraints\MinLength;
1389+
use Symfony\Component\Validator\Constraints\Collection;
1390+
1391+
class ContactType extends AbstractType
1392+
{
1393+
// ...
1394+
1395+
public function getDefaultOptions(array $options)
1396+
{
1397+
$collectionConstraint = new Collection(array(
1398+
'name' => new MinLength(5)
1399+
'email' => new Email(array('message' => 'Invalid email address')),
1400+
));
1401+
1402+
$options['validation_constraint'] = $collectionConstraint;
1403+
}
1404+
}
1405+
1406+
Now, you have the flexibility to create forms - with validation - that return
1407+
an array of data, instead of an object. In most cases, it's better - and
1408+
certainly more robust - to bind your form to an object. But for simple forms,
1409+
this is a great approach.
1410+
12981411
Final Thoughts
12991412
--------------
13001413

book/validation.rst

+2
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,8 @@ library. For information on how to use validation groups inside forms, see
765765
.. index::
766766
single: Validation; Validating raw values
767767

768+
.. _book-validation-raw-values:
769+
768770
Validating Values and Arrays
769771
----------------------------
770772

0 commit comments

Comments
 (0)