Skip to content

Commit

Permalink
Rewrote a part of the Forms guide
Browse files Browse the repository at this point in the history
  • Loading branch information
Bernhard Schussek authored and fabpot committed Jun 30, 2010
1 parent 7d73731 commit cbc2cfe
Showing 1 changed file with 93 additions and 91 deletions.
184 changes: 93 additions & 91 deletions guides/en/Forms.markdown
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
Forms
=====

Symfony 2.0 features a sophisticated Form component that allows you to easily
Symfony2 features a sophisticated Form component that allows you to easily
create mighty HTML forms.

Creating Forms
--------------
Your First Form
---------------

A form in Symfony 2.0 is a view on your objects. Imagine that you give the
visitor of your website a domain object. He then sets the values in the object
and hands it back to you. You can use the Validator to validate the object,
and if the validation fails, you give the object back to the customer and the
cycle continues.
A form in Symfony2 is a transparent layer on top of your domain model. It
reads properties from an object, displays the values in the form and allows
the user to change them. When the form is submitted, the values are written
back into the object.

Let's see how this works in a practical example. Let's create a simple
`Customer` class that can be found in many web applications.
`Customer` class.

[php]
class Customer
{
public $firstName;
public $lastName;
public $age = 20;
public $email;
public $gender;
public $name;
public static function getGenders()
{
return array('male', 'female');
private $age = 20;
public function getAge() {
return $this->age;
}
public function setAge($age) {
$this->age = $age;
}
}

For the sake of simplicity in this tutorial, all the fields in this class
are public. In your application you would probably make them protected and
create setters and getters to read or manipulate them.
The class contains two properties `name` and "age". The property `$name` is
public, while `$age` can only be modified through setters and getters.

Now let's create a form to let the visitor fill the data of the object.

Expand All @@ -44,33 +43,29 @@ Now let's create a form to let the visitor fill the data of the object.
$customer = new Customer();
$form = new Form('customer', $customer, $this->container->getValidatorService());
$form->add(new TextField('firstName'));
$form->add(new TextField('lastName'));
$form->add(new TextField('name'));
$form->add(new IntegerField('age'));
$form->add(new TextField('email'));
$form->add(new ChoiceField('gender', array(
'choices' => array_combine(User::getGenders(), User::getGenders()),
)));

return $this->render('HelloBundle:Hello:signup', array('form' => $form));
}

The form consists of a number of fields. Each field needs a name, which is also
the name of the property that is modified in the underlying object. Now let's
create a simple template to render the form.
A form consists of various fields. Each field represents a property in your
class. The property must have the same name as the field and must either be
public or accessible through public getters and setters. Now let's create a
simple template to render the form.

[php]
# src/Application/HelloBundle/Resources/views/Hello/signup.php
<?php $view->extend('HelloBundle::layout') ?>

<?php echo $form->renderFormTag() ?>
<?php echo $form->renderFormTag('#') ?>
<?php echo $form->renderErrors() ?>
<?php echo $form->render() ?>
<input type="submit" value="Send!" />
</form>

That's all to display a fully functional form! But what if the user submits the
form? We still need a few more lines of code to handle that.
When the user submits the form, we also need to handle the submitted data.
All the data is stored in a POST parameter with the name of the form.

[php]
# src/Application/HelloBundle/Controller/HelloController.php
Expand All @@ -94,43 +89,43 @@ form? We still need a few more lines of code to handle that.
return $this->render('HelloBundle:Hello:signup', array('form' => $form));
}

All the form data is submitted in a POST parameter with the name of the form.
This parameter needs to be bound to the form. Symfony then automatically fills
your object with the data and launches the validation. We're finished!
Congratulations! You just created your first fully-functional form with
Symfony2.

Form Fields
-----------

A form usually consists of one or more form fields. In Symfony 2.0, form
fields are objects that render HTML tags and know how to translate the values
submitted in these tags to some PHP data type.
As you have learned, a form consists of one or more form fields. In Symfony2,
form fields have two responsibilities:

* Render HTML
* Convert data between normalized and humane representations

Let's look at the `DateField` for example. While you probably prefer to store
dates as strings or `DateTime` objects, visitors usually like to enter them
in text input fields or by choosing from a list of drop downs. `DateField`
handles the rendering and type conversion for you.
dates as strings or `DateTime` objects, users rather like to choose them from a
list of drop downs. `DateField` handles the rendering and type conversion for you.

### Basic Fields

Symfony 2.0 ships with the following fields:
Symfony2 ships with all fields available in plain HTML.

<table>
<tr><th>Field Name</th><th>Description</th></tr>
<tr>
<td>TextField</td>
<td>An input tag for entering text</td>
<td>An input tag for entering short text</td>
</tr>
<tr>
<td>TextareaField</td>
<td>A textarea tag for entering more text</td>
<td>A textarea tag for entering long text</td>
</tr>
<tr>
<td>CheckboxField</td>
<td>A checkbox input tag</td>
<td>A checkbox</td>
</tr>
<tr>
<td>ChoiceField</td>
<td>A drop-down, radio-button or checkbox list for selecting one or more values</td>
<td>A drop-down or multiple radio-buttons/checkboxes for selecting values</td>
</tr>
<tr>
<td>PasswordField</td>
Expand All @@ -151,73 +146,47 @@ the locale of the user.
<tr><th>Field Name</th><th>Description</th></tr>
<tr>
<td>NumberField</td>
<td>A localized text input tag for entering numbers</td>
<td>A text field for entering numbers</td>
</tr>
<tr>
<td>IntegerField</td>
<td>A localized text input tag for entering integers</td>
<td>A text field for entering integers</td>
</tr>
<tr>
<td>PercentField</td>
<td>A localized text input tag for entering percent values</td>
<td>A text field for entering percent values</td>
</tr>
<tr>
<td>MoneyField</td>
<td>A localized text input tag for entering money values</td>
<td>A text field for entering money values</td>
</tr>
<tr>
<td>DateField</td>
<td>A localized text input tag or a list of select tags for entering dates</td>
<td>A text field or multiple drop-downs for entering dates</td>
</tr>
<tr>
<td>BirthdayField</td>
<td>An extension of `DateField` for selecting birthdays</td>
<td>An extension of DateField for selecting birthdays</td>
</tr>
<tr>
<td>TimeField</td>
<td>A localized text input tag or a list of select tags for entering dates</td>
<td>A text field or multiple drop-downs for entering a time</td>
</tr>
<tr>
<td>DateTimeField</td>
<td>A combination of `DateField` and `TimeField`</td>
<td>A combination of DateField and TimeField</td>
</tr>
<tr>
<td>TimezoneField</td>
<td>An extension of `ChoiceField` for selecting a timezone</td>
<td>An extension of ChoiceField for selecting a timezone</td>
</tr>
</table>

### Repeated Fields

The special `RepeatedField` allows you to output another field twice.
The field will only validate if the user enters the same value in both fields.

[php]
$form->add(new RepeatedField(new TextField('email')));

### Collection Fields

The `CollectionField` is a special field for manipulating arrays. Let's extend
the `Customer` class to store up to three email addresses.

[php]
class Customer
{
// other properties ...
public $emails = array('', '', '');
}

Now let's add a `CollectionField` to manipulate the addresses.

[php]
$form->add(new CollectionField(new TextField('emails')));

### Field Groups

Field groups allow you to combine multiple fields together. While normal fields
only allow you to edit scalar data types, field groups can be used to edit
related records of an object. Let's add a new class `Address` to our model.
whole objects or arrays. Let's add a new class `Address` to our model.

[php]
class Address
Expand All @@ -226,7 +195,8 @@ related records of an object. Let's add a new class `Address` to our model.
public $zipCode;
}

Let's also add a new property `$address` to the customer.
Now we can add a property `$address` to the customer that stores one `Address`
object.

[php]
class Customer
Expand All @@ -236,7 +206,8 @@ Let's also add a new property `$address` to the customer.
public $address;
}

Now the last missing step is to adapt the controller.
We can use a field group to show fields for the customer and the nested address
at the same time.

[php]
# src/Application/HelloBundle/Controller/HelloController.php
Expand All @@ -255,16 +226,47 @@ Now the last missing step is to adapt the controller.
// process form ...
}

That's all that is required to edit related objects in your form! Since
the `Form` class is an extension of `FieldGroup`, you can also add forms to
other forms, or edit one-to-many relations by combining `CollectionField` and
`FieldGroup`. The architecture of the Form component was designed to give you
the greates possible flexibility!
With only these little changes you can now edit also the `Address` object!
Cool, ey?

### Repeated Fields

The `RepeatedField` is an extended field group that allows you to output a field
twice. The repeated field will only validate if the user enters the same value
in both fields.

[php]
$form->add(new RepeatedField(new TextField('email')));

This is a very useful field for querying email addresses or passwords!

### Collection Fields

The `CollectionField` is a special field group for manipulating arrays or
objects that implement the interface `Traversable`. To demonstrate this, we
will extend the `Customer` class to store three email addresses.

[php]
class Customer
{
// other properties ...
public $emails = array('', '', '');
}

We will now add a `CollectionField` to manipulate these addresses.

[php]
$form->add(new CollectionField(new TextField('emails')));

If you set the option "modifiable" to `true`, you can even add or remove rows
in the collection via Javascript! The `CollectionField` will notice it and
resize the underlying array accordingly.

Form Validation
---------------

You have already learnt in the last part of this tutorial how to set up
You have already learned in the last part of this tutorial how to set up
validation constraints for a PHP class. The nice thing is that this is enough
to validate a Form! Remember that a form is nothing more than a gateway for
changing data in an object.
Expand Down Expand Up @@ -378,7 +380,7 @@ the form output without having to deal with (much) PHP!
Final Thoughts
--------------

This chapter showed you how the Form component of Symfony 2.0 can help you to
This chapter showed you how the Form component of Symfony2 can help you to
rapidly create forms for your domain objects. The component embraces a strict
separation between business logic and presentation. Many fields are
automatically localized to make your visitors feel comfortable on your website.
Expand Down

0 comments on commit cbc2cfe

Please sign in to comment.