Symfony Tips & Tricks III: Generalizing and formatting forms

As you may know Symfony has extended support for forms, which goes from easily creating all kinds of form fields to validating them and eventually … formatting them.

Now the common approach to formatting a form, and the approach that symfony offers you by default when using doctrine:build-forms is to render each error, label and field separately. This has the advantage that you have full control over any customizing, but also has a few drawbacks:

Help texts are not added by default and need to be manually inserted

You’ll have a lot of code duplication that is not easily handled with partials

You can much more easily get inconsistencies.

You’ll need to manually add or remove any fields you add/delete, as well as customize them each time you change the form model.

Generalizing your forms

To avoid all this Symfony can also handle auto-generating the entire form for you.

Of course when you check this out you’ll notice that only the fields have been created, not even the <form&rt; tag or the submit button have been added. This will once again mean code repetition, so to prevent this I created a partial.

// /apps/frontend/layout/_form.php

renderFormTag($action); ?>

" />

Now we have successfully generalized our form we can include it from just about anywhere. Ex. on the login page.

Customizing your generalized forms

Now you probably wonder: but what about customizing? What about the designer? Or the frontend programmer?
No problem! First of all you can do a lot with CSS, but if that wasn’t enough, you can do any change on the form you require right in your template.

As a side-note you can notice I used translation only for the submit button – why? Because forms will automatically be translated. And to get their translation strings you can use the sfFormExtractorPlugin, which I wrote about in my I18n Message Extraction article.

You can change just about anything about your form with simple setters and it’s your own choice if you put the setters here, or put it in the configure() method of your custom forms. (I’d personally put them in the lib/form directory, but I can understand why a designer doesn’t want to work there).

The sfWidgetFormFormatter

Now if you use this method more extensively as I do you might come across some forms where you want to format just a tad different, or perhaps, like me, you want to change the general rules for form formatting.

For example you might want the ‘help’ instructions to appear above the field and the error, instead of below it and put them inside a div with a class so you can style them. Here’s how you’d do that:// /lib/form/doctrine/BaseFormDoctrine.class.php
abstract class BaseFormDoctrine extends sfFormDoctrine // note that you can also do this in BaseForm or BaseFormPropel (the latter I never tried)
{
public function setup()
{
$help_format = "

Of course for that you’d need to change our global form:// /apps/frontend/layout/_form.php

renderFormTag($action); ?>

" />

Is it me or did that form just became a ton simpler? That’s because Symfony automatically recognizes if it’s within a table and thus removes all table elements. Pretty nifty eh? But if you’d just process this you’d still have everything behind each other without organizing. Again you can use the formFormatter for this.// /lib/form/doctrine/BaseFormDoctrine.class.php

abstract class BaseFormDoctrine extends sfFormDoctrine // note that you can also do this in BaseForm or BaseFormPropel (the latter I never tried)
{
public function setup()
{
$row_format = "