In templates, HTML tags of form elements are very often mixed with PHP code. Form helpers in symfony aim to simplify this task and to avoid opening <?php echo tags repeatedly in the middle of <input> tags.

10.1.1. Main Form Tag

As explained in the previous chapter, you must use the form_tag() helper to create a form, since it transforms the action given as a parameter into a routed URL. The second argument can support additional options — for instance, to change the default method, change the default enctype, or specify other attributes. Listing 10-1 shows examples.

Listing 10-1 - The form_tag() Helper

<?php echo form_tag('test/save') ?>
 => <form method="post" action="/path/to/save">

<?php echo form_tag('test/save', 'method=get multipart=true class=simpleForm') ?>
 => <form method="get" enctype="multipart/form-data" class="simpleForm"action="/path/to/save">

As there is no need for a closing form helper, you should use the HTML </form> tag, even if it doesn't look good in your source code.

10.1.2. Standard Form Elements

With form helpers, each element in a form is given an id attribute deduced from its name attribute by default. This is not the only useful convention. See Listing 10-2 for a full list of standard form helpers and their options.

Listing 10-2 - Standard Form Helpers Syntax

// Text field (input)
<?php echo input_tag('name', 'default value') ?>
 => <input type="text" name="name" id="name" value="default value" />

// All form helpers accept an additional options parameter
// It allows you to add custom attributes to the generated tag
<?php echo input_tag('name', 'default value', 'maxlength=20') ?>
 => <input type="text" name="name" id="name" value="default value" maxlength="20" />

// Long text field (text area)
<?php echo textarea_tag('name', 'default content', 'size=10x20') ?>
 => <textarea name="name" id="name" cols="10" rows="20">
      default content
    </textarea>

// Check box
<?php echo checkbox_tag('single', 1, true) ?>
<?php echo checkbox_tag('driverslicense', 'B', false) ?>
 => <input type="checkbox" name="single" id="single" value="1" checked="checked" />
    <input type="checkbox" name="driverslicense" id="driverslicense" value="B" />

// Radio button
<?php echo radiobutton_tag('status[]', 'value1', true) ?>
<?php echo radiobutton_tag('status[]', 'value2', false) ?>
 => <input type="radio" name="status[]" id="status_value1" value="value1" checked="checked" />
    <input type="radio" name="status[]" id="status_value2" value="value2" />

// Dropdown list (select)
<?php echo select_tag('payment',
  '<option selected="selected">Visa</option>
   <option>Eurocard</option>
   <option>Mastercard</option>')
?>
 => <select name="payment" id="payment">
      <option selected="selected">Visa</option>
      <option>Eurocard</option>
      <option>Mastercard</option>
    </select>

// List of options for a select tag
<?php echo options_for_select(array('Visa', 'Eurocard', 'Mastercard'), 0) ?>
 => <option value="0" selected="selected">Visa</option>
    <option value="1">Eurocard</option>
    <option value="2">Mastercard</option>

// Dropdown helper combined with a list of options
<?php echo select_tag('payment', options_for_select(array(
  'Visa',
  'Eurocard',
  'Mastercard'
), 0)) ?>
 => <select name="payment" id="payment">
      <option value="0" selected="selected">Visa</option>
      <option value="1">Eurocard</option>
      <option value="2">Mastercard</option>
    </select>

// To specify option names, use an associative array
<?php echo select_tag('name', options_for_select(array(
  'Steve'  => 'Steve',
  'Bob'    => 'Bob',
  'Albert' => 'Albert',
  'Ian'    => 'Ian',
  'Buck'   => 'Buck'
), 'Ian')) ?>
 => <select name="name" id="name">
      <option value="Steve">Steve</option>
      <option value="Bob">Bob</option>
      <option value="Albert">Albert</option>
      <option value="Ian" selected="selected">Ian</option>
      <option value="Buck">Buck</option>
    </select>

// Dropdown list with multiple selection (selected values can be an array)
<?php echo select_tag('payment', options_for_select(
  array('Visa' => 'Visa', 'Eurocard' => 'Eurocard', 'Mastercard' => 'Mastercard'),
  array('Visa', 'Mastercard'),
), array('multiple' => true))) ?>

 => <select name="payment[]" id="payment" multiple="multiple">
      <option value="Visa" selected="selected">Visa</option>
      <option value="Eurocard">Eurocard</option>
      <option value="Mastercard">Mastercard</option>
    </select>
// Drop-down list with multiple selection (selected values can be an array)
<?php echo select_tag('payment', options_for_select(
  array('Visa' => 'Visa', 'Eurocard' => 'Eurocard', 'Mastercard' => 'Mastercard'),
  array('Visa', 'Mastercard')
), 'multiple=multiple') ?>
 => <select name="payment[]" id="payment" multiple="multiple">
      <option value="Visa" selected="selected">Visa</option>
      <option value="Eurocard">Eurocard</option>
      <option value="Mastercard" selected="selected">Mastercard</option>
    </select>

// Upload file field
<?php echo input_file_tag('name') ?>
 => <input type="file" name="name" id="name" value="" />

// Password field
<?php echo input_password_tag('name', 'value') ?>
 => <input type="password" name="name" id="name" value="value" />

// Hidden field
<?php echo input_hidden_tag('name', 'value') ?>
 => <input type="hidden" name="name" id="name" value="value" />

// Submit button (as text)
<?php echo submit_tag('Save') ?>
 => <input type="submit" name="submit" value="Save" />

// Submit button (as image)
<?php echo submit_image_tag('submit_img') ?>
 => <input type="image" name="submit" src="/images/submit_img.png" />

The submit_image_tag() helper uses the same syntax and has the same advantages as the image_tag().

Note For radio buttons, the id attribute is not set by default to the value of the name attribute, but to a combination of the name and the value. That's because you need to have several radio button tags with the same name to obtain the automated "deselecting the previous one when selecting another" feature, and the id=name convention would imply having several HTML tags with the same id attribute in your page, which is strictly forbidden.

Symfony offers specialized form helpers to do asynchronous requests in the background. The next chapter, which focuses on Ajax, provides more details.

10.1.3. Date Input Widgets

Forms are often used to retrieve dates. Dates in the wrong format are the main reason for form-submission failures. The input_date_tag() helper can assist the user in entering a date with an interactive JavaScript calendar, if you set the rich option to true, as shown in Figure 10-1.

Rich date input tag

Figure 10.1 Rich date input tag

If the rich option is omitted, the helper echoes three <select> tags populated with a range of months, days, and years. You can display these drop-downs separately by calling their helpers (select_day_tag(), select_month_tag(), and select_year_tag()). The default values of these elements are the current day, month, and year. Listing 10-3 shows the input date helpers.

Listing 10-3 - Input Date Helpers

<?php echo input_date_tag('dateofbirth', '2005-05-03', 'rich=true') ?>
 => a text input tag together with a calendar widget

// The following helpers require the DateForm helper group
<?php use_helper('DateForm') ?>

<?php echo select_day_tag('day', 1, 'include_custom=Choose a day') ?>
=> <select name="day" id="day">
      <option value="">Choose a day</option>
      <option value="1" selected="selected">01</option>
      <option value="2">02</option>
      ...
      <option value="31">31</option>
    </select>

<?php echo select_month_tag('month', 1, 'include_custom=Choose a month use_short_month=true') ?>
=> <select name="month" id="month">
      <option value="">Choose a month</option>
      <option value="1" selected="selected">Jan</option>
      <option value="2">Feb</option>
      ...
      <option value="12">Dec</option>
    </select>

<?php echo select_year_tag('year', 2007, 'include_custom=Choose a year year_end=2010') ?>
 => <select name="year" id="year">
      <option value="">Choose a year</option>
      <option value="2006">2006</option>
      <option value="2007" selected="selected">2007</option>
      ...
    </select>

The accepted date values for the input_date_tag() helper are the ones recognized by the strtotime() PHP function. Listing 10-4 shows which formats can be used, and Listing 10-5 shows the ones that must be avoided.

Listing 10-4 - Accepted Date Formats in Date Helpers

// Work fine
<?php echo input_date_tag('test', '2006-04-01', 'rich=true') ?>
<?php echo input_date_tag('test', 1143884373, 'rich=true') ?>
<?php echo input_date_tag('test', 'now', 'rich=true') ?>
<?php echo input_date_tag('test', '23 October 2005', 'rich=true') ?>
<?php echo input_date_tag('test', 'next tuesday', 'rich=true') ?>
<?php echo input_date_tag('test', '1 week 2 days 4 hours 2 seconds', 'rich=true') ?>

// Return null
<?php echo input_date_tag('test', null, 'rich=true') ?>
<?php echo input_date_tag('test', '', 'rich=true') ?>

Listing 10-5 - Incorrect Date Formats in Date Helpers

// Date zero = 01/01/1970
<?php echo input_date_tag('test', 0, 'rich=true') ?>

// Non-English date formats don't work
<?php echo input_date_tag('test', '01/04/2006', 'rich=true') ?>

10.1.4. Rich Text Editing

Rich text editing is also possible in a <textarea> tag, thanks to the integration of the TinyMCE and FCKEditor widgets. They provide a word-processor-like interface with buttons to format text as bold, italic, and other styles, as shown in Figure 10-2.

Rich text editing

Figure 10.2 Rich text editing

Both widgets require manual installation. As the procedure is the same for the two widgets, only the TinyMCE rich text editing is described here. You need to download the editor from the project website (http://tinymce.moxiecode.com/) and unpack it in a temporary folder. Copy the tinymce/jscripts/tiny_mce/ directory into your project web/js/ directory, and define the path to the library in settings.yml, as shown in Listing 10-6.

Listing 10-6 - Setting Up the TinyMCE Library Path

all:
  .settings:
    rich_text_js_dir:  js/tiny_mce

Once this is done, toggle the use of rich text editing in text areas by adding the rich=true option. You can also specify custom options for the JavaScript editor using the tinymce_options option. Listing 10-7 shows examples.

Listing 10-7 - Rich Text Area

<?php echo textarea_tag('name', 'default content', 'rich=true size=10x20') ?>
 => a rich text edit zone powered by TinyMCE
<?php echo textarea_tag('name', 'default content', 'rich=true size=10x20 tinymce_options=language:"fr",theme_advanced_buttons2:"separator"') ?>
=> a rich text edit zone powered by TinyMCE with custom parameters

10.1.5. Country, Language and Currency Selection

You may need to display a country selection field. But since country names are not the same in all languages, the options of a country drop-down list should vary according to the user culture (see Chapter 13 for more information about cultures). As shown in Listing 10-8, the select_country_tag() helper does it all for you: It internationalizes country names and uses the standard ISO country codes for values.

Listing 10-8 - Select Country Tag Helper

<?php echo select_country_tag('country', 'AL') ?>
 => <select name="country" id="country">
      <option value="AF">Afghanistan</option>
      <option value="AL" selected="selected">Albania</option>
      <option value="DZ">Algeria</option>
      <option value="AS">American Samoa</option>
  ...

Similar to select_country_tag() helper, the select_language_tag() helper displays a list of languages, as shown in Listing 10-9.

Listing 10-9 - Select Language Tag Helper

<?php echo select_language_tag('language', 'en') ?>
 => <select name="language" id="language">
      ...
      <option value="elx">Elamite</option>
      <option value="en" selected="selected">English</option>
      <option value="enm">English, Middle (1100-1500)</option>
      <option value="ang">English, Old (ca.450-1100)</option>
      <option value="myv">Erzya</option>
      <option value="eo">Esperanto</option>
      ...

The third helper is the select_currency_tag() helper, that displays a list of currencies, as shown in Listing 10-10.

Listing 10-10 - Select Currency Tag Helper

<?php echo select_currency_tag('currency', 'EUR') ?>
 => <select name="currency" id="currency">
      ...
      <option value="ETB">Ethiopian Birr</option>
      <option value="ETD">Ethiopian Dollar</option>
      <option value="EUR" selected="selected">Euro</option>
      <option value="XBA">European Composite Unit</option>
      <option value="XEU">European Currency Unit</option>
      ...

Note All three helpers accept a third parameter which is an options array. It can restrict the displayed options to a certain set: array('countries' => array ('FR', 'DE')). For select_language_tag() the option is named languages and for select_currency_tag() it is named currencies.

In most cases it makes sense to restrict the set to a list of known and supported values, especially as the lists could contain outdated items.

select_currency_tag() offers an additional option named display that influences what is displayed in the option. This can be set to one of symbol,code or name