Create a Simple Drupal Module - Use the Form API -- Completing the Code

In previous posts we designed our custom module "My Color". We also prepared a directory location, module description files and a simple install routine.

In this post, we will complete the actual module logic.

The My Color module provides:

  • A data entry form.
  • A data entry validation function. I.E. folks must either enter red, white or blue.
  • A data entry submission function, which stores folks color entries in the database.
  • A report of the colors entered.
  • A link to the data entry form.
  • A link to the report page.

Add the following code to the "my_color.module" file:

function my_color_menu() {
    $items['my_color/data_entry_form'] = array(
        'type' => MENU_CALLBACK,
        'access arguments' => array('access content'),
        'page callback' => 'drupal_get_form',
        'page arguments'=>array('my_color_data_entry_form'));
    $items['my_color/display_colors'] = array(
        'type' => MENU_CALLBACK,
        'access arguments' => array('access content'),
        'page callback' => 'display_my_colors_page');
    return $items;
function my_color_data_entry_form() {
    $form = array();
    $form['#redirect'] = 'my_color/display_colors';
        '#default_value'=>' ',
        '#title'=>t('Enter a Color'),
      return $form;
function my_color_data_entry_form_validate($node, &$form_state) {
    $user_entered_color = $form_state['values']['color'];
    $allowed_colors = array("red","blue","white");
    if (! in_array( trim($user_entered_color),$allowed_colors,false)) {
          "Invalid Entry, you must enter either red, white or blue"
    } else {
      "You submitted a valid color: ".$form_state['values']['color']
function my_color_data_entry_form_submit($node, &$form_state) {
    $sql = "insert into {my_color} (name) values ('%s')";
    $db_result = db_query($sql, $form_state['values']['color']);
    if ($db_result) {
         "Color ".$form_state['values']['color'].
         " has been successfully added to the database"
    } else {
           "An unexpected error has occurred. Color".
           $form_state['values']['color']." has not been created");
function display_my_colors_page()
    $db_result = db_query( "select name from {my_color} ");
    $header = array("Color Name");
    // create array and add one element called data
    $rows['data'] = array();
    while ($row = db_fetch_object($db_result)) {
        $rows[] = array($row->name);
    if (count($rows) == 1)
        $rows[] = array("No Colors Entered Yet");
    $link_to_add_form = l('Add More Colors','my_color/data_entry_form');
    return theme_table($header, $rows).'<br/>'.$link_to_add_form;

Explanation of Code.

Menu means Request Dispatcher (URL mapper).

Drupal refers to it's request dispatcher mechanism as a  "menu". In other words, a user makes a request with their web browser location set to http://my_drupal_site/my_module/my_business_function. A Drupal "menu" takes that user's request and dispatches it to your custom application code.

Many developers who are new to Drupal are confused by this unusual use of the word "menu". In other development environments, the request dispatcher is referred to as a "mapper" or "mapping" mechanism.

Drupal also contains "Navigation Menus". That's what most folks think of when they hear "web site menu". However, when developers are writing Drupal modules, they have to realize "Navigation Menu" and "Menu Functions" are seperate and distinct concepts.

How Drupal Finds Your Module Functions

Drupal makes heavy use of naming convention to identify modules and functions. Therefore, it's critical that you use the correct naming pattern for Drupal to identify, and thus call your application code. Note in our code, all public function names are prefaced with "my_color".

"my_color_data_entry_form_validate" -- Note how we preface the function name with the module (my_color). Next we use the form name (data_entry_form), and finally the processing phase name (validatation).

"my_color_data_entry_form_submit" -- Note the naming convention is the same as the validatation phase. We simply substitute the word "validate" with "submit".

Note! this is the default way Drupal finds functions. There are other more advanced methods. However, this is a beginners tutorial.

Detailed Explanations of the functions.

Function: "my_color_menu" -- We are creating 2 links. Each link invokes a different function in our My Color module.

'page callback' => 'drupal_get_form',   -- Instructs Drupal to call a core function (not something we wrote), called "drupal_get_form". This core function secures our data entry form and build all of the infrastructure.

''page arguments'=>array('my_color_data_entry_form') ; -- Instructs Drupal to build and display the form defined in our function "my_color_data_entry_form".

"$items['my_color/data_entry_form'] = array(
'type' => MENU_CALLBACK," -- Creates a URL/Link (e.g. http://my_drupal_site/my_color/data_entry_form). When a user requests that link, Drupal dispatches the request to our form functions ("my_color_data_entry_form.....").

Function: "my_color_data_entry_form" -- We are defiining a text field and a submit button. The "#redirect" statement instructs Drupal to display our report page after the user submits a valid color.

"'#required'=>true," -- Invokes Drupal's built in validation function. If the user fails to enter a value in the "color" field. Drupal will display an error message when the user clicks the submit button.  

Please note! The default Drupal form behavior re-displays a blank form. This confuses many new Drupal developers. Most new developers want their form re-displayed with the values the user just entered. In "My Color", we are instructing Drupal to echo the user's input and display a report page (not the form). This should allow new developers to view how Drupal is processing the various functions.

Function: "my_color_data_entry_form_validate" -- Drupal calls this function after the user clicks the "submit" button on our data entry form. We inspect the value entered by the user. We define 3 colors as valid, "red, white or blue". If a user enters anything other than a valid message, we display an error message. If the user enters a valid value, we display a success message.

Function: "my_color_data_entry_form_submit" --  We attempt to add (insert) the new color entry in to the database table. We capture the database operation's status in the variable "$db_result". If the result is true, we display a success message. If the result is false, we display an error message.

Function: "display_my_colors_page" -- This is our report page. It connects to the database and select all entries from the "my_color" database table. If there are no values, we display a status message "No Colors Entered Yet". If there are values, we add them to a nested array (i.e. an array which contains other arrays like a list of rows). We use the built in Drupal function "theme_table" to display our colors as an html table.

"l('Add More Colors','my_color/data_entry_form');"  -- creates a hyperlink back to our data entry form.

We append the link to our html output. Voila, a report of our colors along with a link to add more colors is rendered.