Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

In Drupal 7, forms were built by a procedural function, and validation and submission were provided by magically named functions: the name of your form building function, followed by either _validate or _submit:


/**
 * Form constructor for the test form.
 *
 * @see form_test_form_test_object_validate().
 * @see form_test_form_test_object_submit().
 */
function form_test_form_test_object($form, &$form_state) {
  $form['element'] = array('#markup' => 'The form_test_form_test_object() function was used for this form.');

  $form['bananas'] = array(
    '#type' => 'textfield',
    '#title' => t('Bananas'),
  );

  $form['actions']['#type'] = 'actions';
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

/**
 * Form validation handler for form_test_form_test_object().
 *
 * @see form_test_form_test_object_submit().
 */
function form_test_form_test_object_validate(&$form, &$form_state) {
  drupal_set_message(t('The form_test_form_test_object_validate() function was used for this form.'));
}

/**
 * Form submission handler for form_test_form_test_object().
 *
 * @see form_test_form_test_object_validate().
 */
function form_test_form_test_object_submit(&$form, &$form_state) {
  drupal_set_message(t('The form_test_form_test_object_submit() function was used for this form.'));
  variable_set('form_test_object_bananas', $form_state['values']['bananas']);
}

This form would be used in this way:
return drupal_get_form('form_test_form_test_object');

In Drupal 8, there is now an interface called FormInterface.

It has four methods:
getFormID()
buildForm()
validateForm()
submitForm()

getFormID() is used to specify the form ID, even though it isn't used by drupal_get_form() or to find the validation or submission, it's still used for hook_form_alter(), theme functions, and the ID attribute of the HTML form element itself.

Here is the Drupal 8 version of the form above:


namespace Drupal\form_test;

use Drupal\Core\Form\FormInterface;

/**
 * Provides a test form object.
 */
class FormTestObject implements FormInterface {

  /**
   * {@inheritdoc}
   */
  public function getFormID() {
    return 'form_test_form_test_object';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, array &$form_state) {
    $form['element'] = array('#markup' => 'The FormTestObject::buildForm() method was used for this form.');

    $form['bananas'] = array(
      '#type' => 'textfield',
      '#title' => t('Bananas'),
    );

    $form['actions']['#type'] = 'actions';
    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Save'),
    );
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, array &$form_state) {
    drupal_set_message(t('The FormTestObject::validateForm() method was used for this form.'));
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, array &$form_state) {
    drupal_set_message(t('The FormTestObject::submitForm() method was used for this form.'));
    Drupal::config('form_test.object')
      ->set('bananas', $form_state['values']['bananas'])
      ->save();
  }

}

This form would be used in this way:
return drupal_get_form('Drupal\form_test\FormTestObject');

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done