Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Apress.Pro.Drupal.7.Development.3rd.Edition.Dec.2010.pdf
Скачиваний:
73
Добавлен:
14.03.2016
Размер:
12.64 Mб
Скачать

CHAPTER 11 THE FORM API

Creating Basic Forms

If you come from a background where you have created your own forms directly in HTML, you may find Drupal’s approach a bit baffling at first. The examples in this section are intended to get you started quickly with your own forms. To begin, we’ll write a simple module that asks you for your name and prints it on the screen. We’ll put it in our own module, so we don’t have to modify any existing code. Our form will have only two elements: the text input field and a Submit button. We’ll start by creating a .info file at sites/all/modules/custom/formexample/formexample.info and entering the following:

name = Form Example

description = Shows how to build a Drupal form package = Pro Drupal Development

core = 7.x files[]=formexample.module

Next, we’ll put the actual module into sites/all/modules/custom/formexample/formexample.module:

<?php

/**

*@file

*Play with the Form API.

*/

/**

* Implements hook_menu(). */

function formexample_menu() { $items['formexample'] = array(

'title' => 'View the sample form', 'page callback' => 'drupal_get_form',

'page arguments' => array('formexample_nameform'), 'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM

);

return $items;

}

/**

* Define a form. */

function formexample_nameform() { $form['user_name'] = array( '#title' => t('Your Name'), '#type' => 'textfield',

'#description' => t('Please enter your name.'),

);

247

CHAPTER 11 THE FORM API

$form['submit'] = array( '#type' => 'submit', '#value' => t('Submit')

);

return $form;

}

/**

* Validate the form. */

function formexample_nameform_validate($form, &$form_state) { if ($form_state['values']['user_name'] == 'King Kong') {

// We notify the form API that this field has failed validation. form_set_error('user_name',

t('King Kong is not allowed to use this form.'));

}

}

/**

* Handle post-validation form submission. */

function formexample_nameform_submit($form, &$form_state) { $name = $form_state['values']['user_name']; drupal_set_message(t('Thanks for filling out the form, %name',

array('%name' => $name)));

}

We’ve implemented the basic functions you need to handle forms: one function to define the form, one to validate it, and one to handle form submission. Additionally, we implemented a menu hook so that visitors can get to our form. Our simple form should look like the one shown in Figure 11-2.

Figure 11-2. A basic form for text input with a Submit button

The bulk of the work goes into populating the form’s data structure, that is, describing the form to Drupal. This information is contained in a nested array that describes the elements and properties of the form and is typically contained in a variable called $form.

248

CHAPTER 11 THE FORM API

The important task of defining a form happens in formexample_nameform() in the preceding example, where we’re providing the minimum amount of information needed for Drupal to display the form.

Note What is the difference between a property and an element? The basic difference is that properties cannot have properties, while elements can. An example of an element is the Submit button. An example of a property is the #type property of the Submit button element. You can always recognize properties, because they are prefixed with the # character. We sometimes call properties keys, because they have a value, and to get to the value, you have to know the name of the key. A common beginner’s mistake is to forget the # before a property name.

Drupal, and you, will be very confused if you do this. If you see the error ‘‘Cannot use string offset as an array in form.inc,’’ you probably forgot the leading # character.

Form Properties

Some properties can be used anywhere, and some can be used only in a given context, like within a button. For a complete list of properties, see the end of this chapter. Here’s a more complex version of a form than that given in our previous example:

$form['#method'] = 'post';

$form['#action'] = 'http://example.com/?q=foo/bar'; $form['#attributes'] = array(

'enctype' => 'multipart/form-data', 'target' => 'name_of_target_frame'

);

$form['#prefix'] = '<div class="my-form-class">'; $form['#suffix'] = '</div>';

The #method property defaults to post and can be omitted. The get method is not supported by the form API and is not usually used in Drupal, because it’s easy to use the automatic parsing of arguments from the path by the menu routing mechanism. The #action property is defined in system_element_info() and defaults to the result of the function request_uri(). This is typically the same URL that displayed the form.

Form IDs

Drupal needs to have some way of uniquely identifying forms, so it can determine which form is submitted when there are multiple forms on a page and can associate forms with the functions that should process that particular form. To uniquely identify a form, we assign each form a form ID. The ID is defined in the call to drupal_get_form(), like this:

drupal_get_form('mymodulename_identifier');

249

Download from Wow! eBook <www.wowebook.com>

CHAPTER 11 THE FORM API

For most forms, the ID is created by the convention “module name” plus an identifier describing what the form does. For example, the user login form is created by the user module and has the ID user_login.

Drupal uses the form ID to determine the names of the default validation, submission, and theme functions for the form. Additionally, Drupal uses the form ID as a basis for generating an HTML ID attribute in the <form> tag for that specific form, so forms in Drupal always have a unique ID. You can override the ID by setting the #id property:

$form['#id'] = 'my-special-css-identifier';

The resulting HTML tag will look something like this:

<form action="/path" "accept-charset="UTF-8" method="post" id="my-special-css-identifier">

The form ID is also embedded into the form as a hidden field named form_id. In our example, we chose formexample_nameform as the form ID because it describes our form. That is, the purpose of our form is for the user to enter his or her name. We could have just used formexample_form, but that’s not very descriptive—and later we might want to add another form to our module.

Fieldsets

Often, you want to split your form up into different fieldsets—the form API makes this easy. Each fieldset is defined in the data structure and has fields defined as children. Let’s add a favorite color field to our example:

function formexample_nameform() { $form['name'] = array(

'#title' => t('Your Name'), '#type' => 'fieldset',

'#description' => t('What people call you.')

);

$form['name']['user_name'] = array(

'#title' => t('Your Name'), '#type' => 'textfield',

'#description' => t('Please enter your name.')

);

$form['color'] = array( '#title' => t('Color'), '#type' => 'fieldset',

'#description' => t('This fieldset contains the Color field.'), '#collapsible' => TRUE,

'#collapsed' => FALSE

);

$form['color_options'] = array( '#type' => 'value',

'#value' => array(t('red'), t('green'), t('blue'))

);

250

CHAPTER 11 THE FORM API

$form['color']['favorite_color'] = array( '#title' => t('Favorite Color'), '#type' => 'select',

'#description' => t('Please select your favorite color.'), '#options' => $form['color_options']['#value']

);

$form['submit'] = array( '#type' => 'submit', '#value' => t('Submit')

);

return $form;

}

The resulting form looks like the one shown in Figure 11-3.

Figure 11-3. A simple form with fieldsets

We used the optional #collapsible and #collapsed properties to tell Drupal to make the second fieldset collapsible using JavaScript by clicking the fieldset title.

251

CHAPTER 11 THE FORM API

Here’s a question for thought: when $form_state['values'] gets passed to the validate and submit functions, will the color field be $form_state['values']['color']['favorite_color'] or $form_state['values']['favorite_color']? In other words, will the value be nested inside the fieldset or not? The answer: it depends. By default, the form processor flattens the form values, so that the following function will work correctly:

function formexample_nameform_submit($form_id, $form_state) { $name = $form_state['values']['user_name'];

$color_key = $form_state['values']['favorite_color'];

$color = $form_state['values']['color_options'][$color_key];

drupal_set_message(t('%name loves the color %color!', array('%name' => $name, '%color' => $color)));

}

The message set by the updated submit handler can be seen in Figure 11-4.

Figure 11-4.Message from the submit handler for the form

If, however, the #tree property is set to TRUE, the data structure of the form will be reflected in the names of the form values. So, if in our form declaration we had said

$form['#tree'] = TRUE;

252

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]