Drupal 模块开发实例之一:表单的…

本文详细介绍如何在Drupal中创建并使用表单模块,从模块信息定义、数据表创建、表单生成、验证与提交全流程解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表单是网站最重要的组成部分,以用户交互为主的站点,表单几乎无处不在。所以,表单的生成、验证、提交,也是程序中很重要的部分,成熟的程序,几乎都有自成体系的表单机制。drupal 也不例外。drupal 的表单系统相当强大,可以让程序员不写任何 html 代码,完成表单的生成、验证、提交、入库等一系列流程。在模块开发中,几乎都会和表单打交道。

这篇教程是 drupal 表单的基本应用实例,涉及表单的定义、验证、提交等基本环节。

本系列教程,都以 drupal 6 为基础,以模块为载体,每篇教程即为一个模块,以后不再做特殊说明。

web 表单交互的基本流程大致是:用户访问某个页面,输出表单界面,用户填写表单,提交,程序验证,通过验证或让用户重新填写。流程基本固定,但实现的方式有许多种,在 drupal 中,这整个流程均可以在模块中完成,甚至不用写一行 html 代码。下面开始创建模块。

模块名称:myform。模块名称根据需要自定义,一般来说,不与现有的第三方模块重名。这个模块我们命名为:myform。

实现功能:定义一个页面,生成一个表单,让所有可以提交信息。

权限设置:不做权限验证,所有人均可提交。本教程重点在表单的基本应用,权限部分留待以后。

以下是详细步骤:

第一步: 定义模块信息,添加模块信息文件:myform.info

1// $Id$
2name = myform
3description = 用户反馈表单
4core = "6.x"


第二步: 创建数据表,添加模块安装文件:myform.install

1、实现 hook_schema,drupal 为了实现多种数据库的兼容,有自成体系的数据库抽象层,包括创建表、增删查,均有详细接口。此部分留待后文讲述。

01
04function myform_schema() {
05  $schema['myform'] = array(
06    'description' => '反馈表单字段',
07    'fields' => array(
08      'id' => array(
09        'type' => 'serial',
10        'unsigned' => true,
11        'not null' => true,
12        'description' => '自增主键'
13      ),
14      'title' => array(
15        'type' => 'varchar',
16        'length' => 255,
17        'not null' => true,
18        'default' => '',
19        'description' => '标题',
20      ),
21      'name' => array(
22        'type' => 'varchar',
23        'length' => 64,
24        'not null' => true,
25        'default' => '',
26        'description' => '昵称',
27      ),
28      'mail' => array(
29        'type' => 'varchar',
30        'length' => 255,
31        'not null' => true,
32        'default' => '',
33        'description' => '邮件',
34      ),
35      'timestamp' => array(
36        'type' => 'int',
37        'not null' => true,
38        'default' => 0,
39        'description' => '留言时间'
40      ),
41      'body' => array(
42        'description' => '留言内容',
43        'type' => 'text',
44        'not null' => false,
45        'size' => 'big',
46        'serialize' => true
47      ),
48    ),
49    'indexes' => array(
50      'timestamp' => array('timestamp'),
51    ),
52    'primary key' => array('id'),
53  );
54  return $schema;
55}


2、实现 hook_install。在模块被安装时,将调用此钩子。通常,若以 hook_schema 定义了数据表结构,将使用 drupal_install_schema 来完成安装。同时,可以在 hook_install 进行其它操作,比如写入一些默认数据等。

1
4function myform_install() {
5  drupal_install_schema('myform');
6}


3、实现 hook_uninstall。在模块卸载时,将调用此钩子。这并不是必须的,但推荐实现,若你的模块创建了数据表,可调用 drupal_uninstall_schema 删除表。注意:用户禁用模块,并不会调用此钩子。
1
4function myform_uninstall() {
5  drupal_uninstall_schema('myform');
6}


第三步: 创建模块主文件,添加模块主文件:myform.module

根据我们的需要,需要定义一个页面,使用 hook_menu 完成。drupal 是一个单入口程序,所有请求均由 index.php 解析分发,hook_menu 定义的路径,实际上就相当于 $_GET['q'],即:index.php?q={path}。用户发起访问请求,系统判断请求路径由哪个模块定义,根据最大匹配原则,找到最接近的定义者。

比如:用户请求的路径为:test/abcd,匹配的顺序大致如:test/abcd -> test/% -> test。如以上三个路径都没有被定义,则返回错误,无法找到页面。以下是本模块需要定义路径。 hook_menu 将被写入数据库 menu 表中,并被缓存,所以,有任何关于 hook_menu 的改动,建议先清除缓存。

注意:如果两个模块定义了相同的路径,将根据 weight 来决定使用谁的配置。

hook_menu 是一个相当重要的钩子,几乎每个模块都要用到,但不是本篇教程的重点,只做以上简单介绍。

01
04function myform_menu() {
05  $item = array();
06    
07  $item['myform'] = array(
08    'description' => '用户反馈',
09    'page callback' => 'drupal_get_form',
10    'page arguments' => array('myform_page_form'),
11    'access callback' => true,
12    'file' => 'myform.page.inc',
13    'type' => MENU_CALLBACK,
14  );
15    
16  return $item;
17}


第四步: 创建表单,创建文件:myform.page.inc

为什么要将表单代码写在另一个文件呢?drupal 在每次初始化时,将加载每个模块的主文件(如:myform.module),我们可以把只在特定路径使用到的代码,写在另一个文件里,减少主模块文件的大小,以加速系统运行。当然,这所带来的效率提升可能是微乎其微,甚至没有,但养成这个习惯也不是坏事,另外这也让模块的文件结构更清晰,易于维护。

根据 hook_menu 里的定义,drupal_get_form 是页面回调函数,相当于:drupal_get_form('myform_page_form')。我们只需要按规定格式定义表单,然后调用 drupal_get_form,便能得 html 代码,输出到页面即可。

在 myform.page.inc 中创建表单函数:myform_page_form。

1
5function myform_page_form(&$form_state) {
6}


这儿有一个参数: &$form_state,这是 drupal_get_form 自动传递的,其中包含表单 id、token 等信息,若处于验证或提交环节,包含所有用户输入值,即 $_POST。使用 drupal_get_form 也可以传递自定义参数,比如:drupal_get_form('myform_page_form', $test),那么 myform_page_form 函数则要这样:

1
7function myform_page_form(&$form_state, $test) {
8}


此处不做深入讨论,回到本教程,创建表单的全部代码如下:
01
05function myform_page_form(&$form_state) {
06    
07  $form['title'] = array(
08    '#title' => '主题', // 字段名称
09    '#type' => 'textfield', // 字段类型,此处为单行文本
10    '#required' => true, // 是否必填
11    '#default_value' => '', // 默认值,可选
12  );
13    
14  $form['name'] = array(
15    '#title' => '昵称',
16    '#type' => 'textfield',
17    '#required' => true,
18    '#description' => '请输入您的昵称,不低于 2 个字符'
19  );
20    
21  $form['mail'] = array(
22    '#title' => '邮件',
23    '#type' => 'textfield',
24    '#required' => true,
25    '#description' => '请输入您的常用邮件,便于我们联系您'
26  );
27    
28  $form['body'] = array(
29    '#title' => '内容',
30    '#type' => 'textarea', // 多行文本
31    '#required' => true,
32  );
33    
34  
41  $form['#validate'] = array('myform_page_form_validate');
42    
43  
50  $form['submit'] = array(
51    '#type' => 'submit', // 提交按钮
52    '#value' => '确认提交', // 按钮值
53    '#submit' => array('myform_page_form_submit'), // 提交函数
54  );
55    
56  return $form;
57}


接下来是表单验证函数。刚接触 drupal 的朋友可能有这个疑惑,drupal 为什么要把表单的验证和提交环节分开呢,这不是影响效率吗,验证完毕不是可以直接做入库等提交操作吗?实际上,这是为了让表单机制更灵活,假设验证和提交环节不分开,某个模块定义了表单,其它模块也想要验证这个表单,怎么办?验证和提交分离,其它模块可以轻松的通过 hook_form_alter 添加一个验证函数,在该函数中,可阻止表单提交。国内很多程序,均不考虑这些需要,所以,如果要进行二次开发,只有在源代码上进行修改,缺乏灵活性。myform_page_form 表单的验证函数代码如下:
01
08function myform_page_form_validate(&$form, &$form_state) {
09    
10  
15  if (drupal_strlen($form_state['values']['name']) < 2) {
16    
20    form_set_error('name', '昵称不能少于 2 个字符');
21  } else if (drupal_strlen($form_state['values']['title']) > 255) {
22    form_set_error('title', '标题长度不能大于 255 个字符');
23  }
24    
25  // 如验证通过,将进入表单提交环节
26}


以上只验证了长度是否合法,实际应用中,可能还需要验证电子邮件是否合法等。验证通过后,进行提交环节,代码如下:

01
06function myform_page_form_submit(&$form, &$form_state) {
07  
10  db_query("INSERT INTO {myform} (id, title, name, mail, timestamp, body) 
11  VALUES (null, '%s', '%s', '%s', %d, '%s')", $form_state['values']['title'], 
12  $form_state['values']['name'], $form_state['values']['mail'], 
13  $_SERVER['REQUEST_TIME'], $form_state['values']['body']);
14    
15  // 获取上一条 insert sql 返回的主键,以此判断是否执行成功
16  if (db_last_insert_id('myform', 'id')) {
17      
18    
22    drupal_set_message('感谢您,反馈已经提交,我们将尽快和您取得联系');
23      
24    // 如果想将用户重定向到一个页面,可修改 $form['#redirect'] 值,如:
25      
26    $form['#redirect'] = 'test/abcde';
27      
28    
32      
33  } else {
34      
35    // 数据写入失败了
36    drupal_set_message('抱歉,遇到问题,提交失败了', 'error');
37      
38  }
39    
40}


表单成功写入数据库,整个表单的流程就走完了。很简单吧?因为规则不熟悉,可能不明白为什么要这样写,实际上,刚开始做模块开发,只需要知道要这样即可以,不必深究为什么要这样。倘若先拿一本书,务必把每个术语搞清楚,理解透彻,没有实际开发经验,我想还是比较困难的。好读书不求甚解,大概也是这个道理吧。做多了,自然就明白了,可能我是实践主义者。

以上就是本篇教程的全部内容,下一篇将继续研究表单,说说关于文件上传。

启用后,访问 http://www.mysite.com/?q=myform 即可提交表单。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值