Last updated 8 October 2013. Created on 26 November 2012.
Edited by meustrus, Gaelan. Log in to edit this page.

Incoming $_POST data is first sanitized and checked against the structure of the form before being handed off to validate and submit handlers. The 'values' key is used to store this collection of data. This key replaces the old separate $form_values variable that was passed to submit and validate handlers.
The following three keys can be used to control the rendering and processing workflow of the form. Validation and submission handlers can modify the data in these three keys to alter the form workflow based on user input.
The 'redirect' key controls what happens after a form's processing is complete. By default, the page with the form on it will reload, so the form's fields can be cleared out. If 'redirect' is set to a Drupal path (like user/edit), the user will be redirected to that path instead. If 'redirect' is set to FALSE, the user will not be redirected after the form is processed -- the values they entered into the form will remain in the fields.
The 'rebuild' key overrides the 'redirect' key: when it is set to TRUE, the form will be rebuilt from scratch and displayed on screen. This gives form construction code a chance to add additional fields or alter the structure of the form based on user input (For example, re-building the form with additional fields if the user clicks 'give me more choices'). If this flag is set by a validation handler, any 'submit' handlers will be skipped. If it's set by a 'submit' handler, the form will be rebuilt and displayed after all submit handlers have finished processing.
When building complex forms that require multiple steps for completion (for example, a three-page survey), it's necessary to preserve the data from all steps so that they can be processed together at the end. (And, on occasion, to vary the contents of one step based on the input from the previous one). Any data placed in the 'storage' bin of the $form_state collection will automatically be cached and re-loaded when the form is next submitted, allowing your code to accumulate data from step to step and process it in the final stage without any additional code. Developers who want more control can use their own caching mechanisms to store temporary form data (the user session and hidden form fields are two popular alternatives), but the 'storage' bin is automatically handled for you by FormAPI.
Note that if $form_state['storage'] is populated, $form_state['rebuild'] is automatically set to TRUE.
These three keys store information about the current processing state of the form. If 'submitted' is TRUE, user input is currently being processed. The 'submit_handlers' and 'validate_handlers' keys hold any custom validation or submission handlers that were attached to the specific button clicked by the user.
A full copy of the button element that was clicked to submit the form. This is more reliable than the old $form_values['op'] name, and also carries any additional information that was placed in the button element's form definition.

Looking for support? Visit the forums, or join #drupal-support in IRC.


meustrus’s picture

For complete information on the $form_state array in later versions of Drupal, see the API documentation:

Drupal 7: drupal_build_form (includes/
Drupal 8: drupal_build_form (core/includes/

Arla’s picture

In Drupal 8, the $form_state array structure is discarded in favor of a FormState class. See the FormStateInterface API documentation. There is some more information in the change record: $form_state is now a classed object.

pit1988’s picture

Hi, which $form_state should i use to get values from tableselect's default checkboxes ?

Trejkaz’s picture

There is this claim:

"Incoming $_POST data is first sanitized and checked against the structure of the form before being handed off to validate and submit handlers."

But what I'm seeing is that a value which should only be a string (form_state['values']['user'], for the user_login form) is coming through as an array. So I'm finding I have to sanitise the values myself in the validate handler, but I certainly think it would be nice if this were done for me somehow.