这一章感觉像是讲Drupal的模板引擎,Drupal提供了一个应用程序接口(API),用来生成、验证和处理HTML表单。表单API将表单抽象为一个嵌套数组,里面包含了属性和值。在生成页面时,表单呈现引擎会在适当的时候将数组呈现出来。一个表单模块:
formexample.info
name = Form Example description = Shows how to build a Drupal form package = Pro Drupal Development core = 7.x files[]=formexample.module
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( // 传给page callback的参数
'formexample_nameform'
),
'access callback' => TRUE, // 用户是否可以访问,默认为 user_access() ,也可以用常量来代替它
'type' => MENU_NORMAL_ITEM
);
return $items;
}
/**
* Define a form.
* 上面的page callback其实存放的是函数名称,该函数生成一个嵌套数组
*/
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(
// 直接在这里使用html标记不够干净,应当使用主题函数
// '#prefix' => '<hr />',
'#title' => t('Color'),
'#type' => 'fieldset',
// '#suffix' => '<div class="privacy-warning">' .
// t('This information will be displayed publicly!') . '</div>',
'#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')
)
);
$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;
}
/**
* 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.
// 指明user_name表单域验证失败
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)
// {
// $color_key = $form_state['values']['favorite_color']; // 0
// $color = $form_state['values']['color_options'][$color_key]; // red1
// // rdump($form_state);
// // rdump($color_key);
// // rdump($color, TRUE);
// $name = $form_state['values']['user_name'];
// drupal_set_message(t('Thanks for filling out the form, %name', array(
// '%name' => $name
// )));
// }
function formexample_nameform_submit($form, $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
)));
}
/**
* Implements hook_theme().
*/
function formexample_theme()
{
return array(
'formexample_nameform' => array(
'render element' => 'form',
'template' => 'formexample-nameform' // 指定将要使用formexample-nameform.tpl.php来渲染
)
);
}
/**
* Assign the elements of the form to variables so
* the themer can use those values to control how the
* form elements are displayed, or alternatively
* displaying the whole form as constructed above.
*/
function template_preprocess_formexample_nameform(&$variables)
{
// 直接return的话页面没法渲染
// return ;
$variables['formexample_nameform'] = array();
$hidden = array();
// Provide variables named after form keys so themers can print each element independently.
// 提供变量名和键以便主题可以单独打印每个元素
// element_children取出一个数组的子数组
// krumo($variables);
foreach(element_children($variables['form']) as $key)
{
// 通过element_children知道子数组的名称,比如name color color_options submit form_build_id form_token form_id
// dpm($key);
// 把子数组的'#type'属性取出来
$type = $variables['form'][$key]['#type'];
if($type == 'hidden' || $type == 'token')
{
// 隐藏域和令牌不用管了
// 令牌,每个表单中都带有它,通过该令牌Drupal能够判定一个表单是一个实际的Drupal表单,而不是一个恶意用户修改后的。
$hidden[] = drupal_render($variables['form'][$key]);
}
else
{
$variables['formexample_nameform'][$key] = drupal_render($variables['form'][$key]);
}
}
// Hidden form elements have no value to themers. No need for separation.
// hidden填入hidden键值
$variables['formexample_nameform']['hidden'] = implode($hidden); // implode() 函数把数组元素组合为一个字符串。
// Collect all form elements to make it easier to print the whole form.
// 所有的页面元素存到formexample_nameform_form里
$variables['formexample_nameform_form'] = implode($variables['formexample_nameform']);
}
formexample-nameform.tpl.php
<?php /** * @file * * This is the template file for rendering the formexample nameform. * In this file each element of the form is rendered individually * instead of the entire form at once, giving me the ultimate control * over how my forms are laid out. I could also print the whole form * at once - using the predefined layout in the module by * printing $variables['formexample_nameform_form']; * 这部分就没啥意思了,把模块里的输出打印出来 * */ print '<div id="formexample_nameform">'; print $variables['formexample_nameform']['color']; print $variables['formexample_nameform']['name']; print $variables['formexample_nameform']['submit']; print $variables['formexample_nameform']['hidden']; print '</div>'; // print $formexample_nameform_form; ?>
最后的效果:

码农场