这一章感觉像是讲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; ?>
最后的效果: