Back to top

Forms

Rack provides a set of classes enable form handling and rendering in include/form.php. This page discusses the public form API.

Form class

The core of Rack's form system is the Form class. All interactions with a form and it's fields should happen through this class, or one of its subclasses.

Initialization

The constructor of the form class takes two arguments, the form's name (which is an id-like string) and a lists of fields. The latter may be left out, as fields can be added through the add_field($field_name, $field) and add_fields($fields) functions.

If the form has been submitted, the fields will automatically be filled with the submitted data once they're added to the form. If needed, this process can be manually executed by calling the function initizize() on the form object.

Sometimes, it may be desirable to populate the fields with default data. This can be done through the populate_field($field_name, $values) and populate_fields($values) functions, which set the values of the fields without overwriting submitted data.

Validation

Forms can be validated through their validate() function, which will return true if the form has been submitted and all fields have valid input and will return false otherwise.

When custom validation is needed, this should generally be done by subclassing the Form class and overriding its validate() function. In some specific cases, it may be more desirable to subclass a single Field class and override its validate() function instead.

Rendering

There are tree main rendering strategies supported. Automatic rendering, semi-automatic rendering and manual rendering. Automatic rendering can be done calling the function render($action=null, array $attributes=[]), which allows for customizing the arguments of the <form> tag.

Semi-automatic rendering can be done by manually calling the function render_field($key, array $attributes=[], array $error_attributes=[], array $parent_attributes=[]) for every field of the form. This renders the form according to the following template

<div $parent_attributes>
   <label></label>
   <field $attributes> 
   <span $error_attributes></span> // for each error
</div>

Manual rendering can be achieved by iterating over the form's fields and calling the field's render(array $attributes=[]) and render_label() functions. The field's errors should then also be rendered manually.

(Semi) Automatic can be customized by subclassing the Form class and overriding its render functions. Rack already provides a class to render forms compatible with Bootstrap 3, called Bootstrap3Form.

Public functions

The Form class exposes the following public functions:

  • __construct($name, array $fields=[])
  • initialize()
  • is_submitted()
  • validate()
  • render(array $attributes=[], $action=null)
  • render_field($key, array $attributes=[], array $error_attributes=[], array $parent_attributes=[])
  • add_field($field_name, $field) and add_fields($fields)
  • delete_field($field_name)
  • get_field($field_name) and get_fields()
  • get_name()
  • get_value($field_name) and get_values()
  • set_value($field_name, $value) and set_values($values)
  • populate_field($field_name, $values) and populate_fields($values)

Fields

Field class

The Field class provides the base implementation for all fields supported by Rack. Its constructor has the following signature __construct($label, $optional=false, array $attributes=[], $name='', $form=null). It should be noted that fields are required by default and the attributes used for rendering the HTML tag of the field (e.g. <input>) can be provided on intialization.

In the default validation strategy, validation fails (returns false) if…

  • …the field is not optional and empty (a string only containing whitespace counts as empty)
  • …the maxlength HTML5 attribute is set and the value is a string that is longer than the defined maxlength
  • …the minlength HTML5 attribute is set and the value is a string that is shorter than the defined minlength

In all other cases, validation succeeds (returns true). Field subclasses may extend or override this strategy.

It should be noted that required fields will render the HTML5 required attribute.

Supported fields

InputField

A general implementation of the HTML <input> element. The constructor has the custom signature __construct($type, $label, $optional=false, array $attributes=[], $name='', $form=null), where $type corresponds to the HTML type attribute. InputField does not implement custom validation.

TextAreaField

An implementation of the HTML <textarea> element. TextAreaField does not implement a custom constructor or custom validation.

SelectField

An implementation of the HTML <select> element. The constructor has the custom signature __construct($label, $options, $optional=false, array $attributes=[], $name='', $form=null)), where $options is an array containing all options of the field. The following snippet demonstrates the accepted formats for the $options array.

$options = [
   // 1) Single value: <option>Option Name</option>
   'Option Name',
   // 2) Value mapped to display name: <option value="option_value">Option Name</option>
   'option_value' => 'Option Name',
   // 3) Single value, with attributes: <option class="class_name" disabled>Option Name</option>
   ['Option Name', ['disabled', 'class' => 'class_name']],
   // 4) Value mapped to display name with attributes: <option value="option_value" class="class_name" disabled>Option Name</option>
   'option_value' => ['Option Name', ['disabled', 'class' => 'class_name']],
];

SelectFields does implement custom validation, which fails if…

  • …the field is not optional and no value has been submitted
  • …the selected value does have the disabled HTML attribute.

Validation succeeds in all other cases.

Please do note that due to PHP limitations, it is impossible to render options with integer keys (array keys) or options with string keys that contain integer values (e.g. "8" or "22").

CheckBoxField

Subclass of InputField to render <input type=“checkbox”> fields. This class does not implement a custom constructor, but it does implement custom validation which fails if the field is not optional and the value is empty.

CheckBoxField implements an additional render function render_with_label(array $attributes=[]) which renders the field as:

<label>
  <input type="checkbox" $attributes>
  $label_text
</label>

StringField

Subclass of InputField to render <input type=“text”> fields. StringField does override the InputField constructor to have the same signature as the Field constructor. It does not implement custom validation.

EmailField

Subclass of InputField to render <input type=“email”> fields. EmailField does override the InputField constructor to have the same signature as the Field constructor.

EmailField does implement custom validation, which fails if…

  • …the field is not optional and no value has been submitted
  • …the value is a valid email address if it would be sanitized.

WARNING! This fields value is NOT sanitized. You should sanitize it ($value = filter_var($value, FILTER_SANITIZE_EMAIL);) before using it!

DateField

Subclass of InputField to render <input type=“date”> fields. StringField implements a custom constructor with the signature __construct($label, $format, $optional=false, array $attributes=[], $name='', $form=null), where $format is a format string accepted by DateTime::createFromFormat.

DateField does implement custom validation, which fails if…

  • …the field is not optional and no value has been submitted
  • …the value does not satisfy the provided format

NumberField

Subclass of InputField to render <input type=“number”> fields. NumberField does override the InputField constructor to have the same signature as the Field constructor.

NumberField does implement custom validation, which fails if…

  • …the default implementation of validate() fails
  • …the value is not numeric
  • …the max HTML5 attribute is set and the value is greater than the defined max
  • …the min HTML5 attribute is set and the value is greater than the defined min

documentation/rack/reference/forms.txt · Last modified: 2023/08/31 23:20 by Martijn Luinstra