Pluf : PHP 5 Framework   Download | Bug Tracking | Source | Documentation | Forum | Latest Changes | Home

Forms Handling

What is a website without forms? Good question, but we do not need to answer as Pluf is providing a robust and efficient way to handle forms.

Form Architecture

When handling data from web forms, you need to perform two distincts but linked operations:

  1. Provide a way to input/display and retrieve the data in the form widget.
  2. Validate the submitted data.

To perform these operations, Pluf is providing two sets of objects, the form widgets and the form fields. The Pluf_Form object itself is a collection of form fields associated with form widgets with optional extra validation routines.

Form Widgets

The form widgets are in charge of displaying the form element corresponding to a given field. For exemple, this could be a simple text input:

<input type="text" value="" name="title" id="id_title" />

Pluf provides a collection of widgets.

Form Fields

The fields are in charge of validating the data returned by the form widgets. The validation will also perform the conversion of the data to the internal PHP form. For example, the value of a checkbox will be converted to the boolean True or False.

Pluf also provides a collection of form fields.

Building a Form with Fields and Widgets

A form extending the Pluf_Form class requires the definition of at least the initFields() method. This method define the fields of the form.

Here is a simple example :

class MyApp_Form_Simple extends Pluf_Form
{
    public function initFields($extra=array())
    {
        $this->fields['name'] = new Pluf_Form_Field_Varchar(
                                      array('required' => true,
                                            'label' => __('List name'),
                                            'initial' => 'Here the name',
                                            'help_text' => __('For example: "Happy stuff".'),
                                            ));

        $this->fields['description'] = new Pluf_Form_Field_Varchar(
                                      array('required' => true,
                                            'label' => __('Description'),
                                            'widget' => 'Pluf_Form_Widget_TextareaInput',
                                            'widget_attrs' => array('rows' => 5,
                                                                'cols' => 75),
                                            ));
    }
}

The order in which the fields are defined is also the order in which they will be displayed in the template if you let the form have the control of the display.

The associative array $this->fields uses the key for the name of the field. For example, the first field will be in the form with name being the name of the form.

<input type="text" name="name" id="id_name" />

Now each field has some options for the display and for the validation of the submitted value. The common options are quite straightforward:

  • required: The field is required.
  • label: The text for the label of the field.
  • initial: Initial value if nothing submitted.
  • help_text: Some explanations to help the user in providing the input.

Now, as we wrote earlier, the fields are performing the validation of the data, but you have also control on the way the data are presented to the user with the use of the right widget.

If we take the description example, you can see that like the name, the value to input is a Varchar, that is a text with a variable length. But, we decided not to use the default rendering widget (a simple text input) but we selected Pluf_Form_Widget_TextareaInput. That is, we want to use a text area for the input and through the widget_attrs option, we passed more options to the widget asking a given number of rows and columns.

Form Usage in the Templates

Here is a simple form usage:

{if $form.errors}
<div class="errors">
<p>The form contains some errors. Please correct them and resubmit it.</p>
{if $form.get_top_errors}
{$form.render_top_errors}
{/if}
</div>
{/if}
<form method="post" action=".">
<table>
{$form.render_table}
<tr>
<td>&nbsp;</td>
<td><input type="submit" name="submit" value="Submit Form" /></td>
</tr>
</table>

First we display the general errors of the form if we have some and then the form. Here the form is rendered without any fine control using the {$form.render_table} call but you can render field by field if you want. For example you could do:

<tr>
<th><strong>{$form.f.description.labelTag}:</strong></th>
<td>{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if}
{$form.f.description|safe}<br />
<span class="help">{$form.f.description.help_text}</span>
</td>
</tr>
<tr>

Extra Validation

The built-in validation routines of the forms are not necessarily all what you need, you may need more control on the data. For example, you may want to ensure that a username is not already in use when doing a registration or other things.

You can add extra validation on a field by field basis and at the end, on all the fields at once.

Extra Field Validation

The extra field validation of a form is a method named clean_nameofthefield() with the following signature:

$cleaned_value = $this->clean_nameofthefield()

For example, suppose we want the name in the previous form to always start with uppercase, we could do the following:

  1. Add a new method clean_name().
  2. Do the check within the method and if error, throw the right exception.

The code example is simple:

    public function clean_name()
    {
        // here we know that the value $name contains
        // a string validated by the base Varchar field.
        $name = $this->cleaned_data['name'];
        $first_letter = mb_substr($name, 0, 1);
        if (mb_strtoupper($first_letter) != $first_letter) {
            throw new Pluf_Form_Invalid('The first letter must be uppercase.');
        }
        return $name;
    }

The error message displayed back to the user is the one given in the Pluf_Form_Invalid exception.

Note: You cannot access other fields like $this->cleaned_data['description'] within the field only extra validation because you don't know if the field has been validated or not.

Full Form Validation

At the end of the validation of all the fields, including the extra clean_*() calls, a full form validation can be performed using the clean() method. This method must return the full associative array of validated data. If one of the previous validation call fails, this method is not called.

    public function clean()
    {
        // Access $this->cleaned_data
        return $this->cleaned_data;
    }

This function is perfect for example to perform a check if two passwords in the form are the same or not:

    public function clean()
    {
        if ($this->cleaned_data['password1'] != $this->cleaned_data['password2']) {
            throw new Pluf_Form_Invalid('The two passwords must match.');
        }
        return $this->cleaned_data;
    }

Report issues in the documentation

If you find errors or issues in the documentation, report a bug. We will update the documentation accordingly.

Pluf © 2005-2008 Loïc d'Anterroches, supported by Céondo Ltd.