当访问 http://www.mysite.com/?q=myform 的时候,会见到如下的表单(Form)
---------------------------------------------------------------------
建立表table
写主模块
我们需要写一个表单(Form),这里就需要通过 hook_menu来完成。在主模块 my_first_module.module 文件里建立一个函数 my_first_module_menu()
function my_first_module_menu() { $item = array(); $item['myform'] = array( 'title' => '第一个表单', 'description' => '我的第一个模块 —— 表单', 'page callback' => 'drupal_get_form', 'page arguments' => array('myform_page_form'), 'access callback' => TRUE, 'file' => 'myform.page.inc', //把myform_page_form 函数写在myform.page.inc里 'type' => MENU_CALLBACK, ); return $item; }
$item先定义路径,在访问 /myform 页面时候,去调用 myform_page_form 函数产生表单,myform_page_form() 函数放在'myform.page.inc'文件里。
每一个$item都是对应一个路径,写在 [ ] 里。当item用一样路径时候,就调用后写那个$items的。(有文章说和weight有关,我测试weight不会影响先后次序)
[ ] 里也可以用通配符,譬如: [node/%/edit]。详细参见:function hook_menu 里的Wildcards in Paths一段
$item数组里每个关键字对应的值如下。
- title 必须
未翻译的主题
- title callback
产生主题的函数。默认是 t()。如果你不想翻译,就设置FALSE (所以我们不必再写 'title' => t('第一个表单'))
- title arguments
传递到 t() 或者 你自定义函数 的参数。可以和路径组件结合
参考:Menu item title and description callbacks, localization
- description
未翻译的说明描述。
- page callback
当用户访问页面路径的时候,调用一个显示网页的函数。如果不写,父菜单的回调函数将代替执行
- page arguments
传递给page callback函数的一串参数数组
- delivery callback
这个函数将调用page callback函数的结果,发送到浏览器上。默认是 drupal_deliver_html_page(),除非值继承了父菜单。
值得注意的是,如果访问检查失败,这个函数也会被调用。所以任何自定义delivery callbcack函数都要考虑到这点。详见 drupal_deliver_html_page() 举例。
- access callback
如果用户有权访问这个菜单项,函数就返回TRUE,否则返回FALSE。它可以是一个布尔常量,而不是一个函数。你也可以用数字表达 (将会被转成布尔值)。默认为user_access(),除非从父菜单继承。只有 MENU_DEFAULT_LOCAL_TASK 项可以继承访问回调。要使用 user_access()默认回调,你必须有指定权限检查"access arguments"
- access arguments
传递给access callback函数的一串数组。如果access callback是继承父菜单,那么access arguments也将随同一起继承。除非子菜单覆盖。
- theme callback
- theme arguments
- file
- file path
- load arguments
- weight
- menu_name
- expanded
- context
- tab_parent
- tab_root
- position
- type
描述菜单项属性的代码。许多快捷代码的常量在 menu.inc 里。
默认是:MENU_NORMAL_ITEM
常用的几个:
创建表单
建立一个 myform.page.inc 的文件,开头别忘记写 <?php,结尾不用写 ?>
function myform_page_form($form, &$form_state) { $form['title'] = array( '#title' => t('标题'), // 字段名称 '#type' => 'textfield', // 字段类型,此处为单行文本 '#required' => true, // 是否必填 '#default_value' => '', // 默认值,可选 ); $form['fullname'] = array( '#title' => '姓名', '#type' => 'textfield', '#required' => true, '#description' => '请输入您的姓名,不低于 2 个字符' ); $form['email'] = array( '#title' => '电子邮件', '#type' => 'textfield', '#required' => true, '#description' => '请输入您的常用邮件,便于我们联系您' ); $form['body'] = array( '#title' => '内容', '#type' => 'textarea', // 多行文本 '#required' => true, ); /** * 表单验证函数,可指定多个,如:array('test_validate1', 'test_validate2'); * 系统将根据顺序,依次调用,若所有函数均通过验证,将进行提交环节。 * * 如果表单没有指定验证函数,drupal 将默认为表单绑定一个函数,名称为:表单函数+下划线+validate * 本例中为:myform_page_form_validate。若此函数存在,将调用此函数来验证表单 */ $form['#validate'] = array('myform_page_form_validate'); /** * 表单提交函数绑定在 submit 类型的表单字段上,可绑定多个提交函数,如:array('test_submit1', 'test_submit2'); * 系统将根据顺序,依次调用。如果在第一个函数中,页面被重定向,后面的函数将不会被调用。 * * 如果表单没有指定提交函数,drupal 将默认为表单绑定一个函数,名称为:表单函数+下划线+submit * 本例中为:myform_page_form_submit。若此函数存在,在验证通过后,将调用此函数。 */ $form['submit'] = array( '#type' => 'submit', // 提交按钮 '#value' => t('确认提交'), // 按钮值 '#submit' => array('myform_page_form_submit'), // 提交函数 ); return $form; }
#type 说明参考:https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7
验证表单函数
/** * 表单验证 * @param (array) &$form * 表单字段 * @param (array) &$form_state * 表单值,用做判断表单的各种参数,包括用户提交的所有数据 */ function myform_page_form_validate(&$form, &$form_state) { /** * 用户提交的所有数据在 $form_state['values'] 之中,相当于 $_POST * 根据需求,验证昵称是否少于 2 个字符,中英文均算一个字符 * 可使用封装好的计算字符串长度函数:drupal_strlen */ if (drupal_strlen($form_state['values']['name']) < 2) { /** * 如果少于 2 个字符,调用 form_set_error() 写入错误信息,系统将显示错误信息,同时阻止表单提交 * form_set_error() 的格式,第一个参数:字段名称,第二个参数:用户将看到的错误信息 */ form_set_error('name', '昵称不能少于 2 个字符'); } else if (drupal_strlen($form_state['values']['title']) > 255) { form_set_error('title', '标题长度不能大于 255 个字符'); } // 如验证通过,将进入表单提交环节 }
提交表单(写入数据库)
/** * 表单提交 * @param (array) &$form * @param (array) &$form_state */ function myform_page_form_submit(&$form, &$form_state) { /** * 写入数据库 */ db_query("INSERT INTO {myform} (id, title, name, mail, timestamp, body) VALUES (null, '%s', '%s', '%s', %d, '%s')", $form_state['values']['title'], $form_state['values']['name'], $form_state['values']['mail'], $_SERVER['REQUEST_TIME'], $form_state['values']['body']); // 获取上一条 insert sql 返回的主键,以此判断是否执行成功 if (db_last_insert_id('myform', 'id')) { /** * 执行成功了,到数据库去看看,是不是有这条记录了 * 显示一条信息给用户 */ drupal_set_message('感谢您,反馈已经提交,我们将尽快和您取得联系'); // 如果想将用户重定向到一个页面,可修改 $form['#redirect'] 值,如: $form['#redirect'] = 'test/abcde'; /** * 这里也可以使用 drupal_goto 来重定向,但这并不是个好方法 * 因为可能还有其它提交函数在 后面排队,被这儿一重定向,后面就没机会执行了 */ } else { // 数据写入失败了 drupal_set_message('抱歉,遇到问题,提交失败了', 'error'); } }