Drupal 模块开发实例之一:表单的…
2012-11-29 14:20
218 查看
表单是网站最重要的组成部分,以用户交互为主的站点,表单几乎无处不在。所以,表单的生成、验证、提交,也是程序中很重要的部分,成熟的程序,几乎都有自成体系的表单机制。drupal
也不例外。drupal 的表单系统相当强大,可以让程序员不写任何 html
代码,完成表单的生成、验证、提交、入库等一系列流程。在模块开发中,几乎都会和表单打交道。
这篇教程是 drupal 表单的基本应用实例,涉及表单的定义、验证、提交等基本环节。
本系列教程,都以 drupal 6 为基础,以模块为载体,每篇教程即为一个模块,以后不再做特殊说明。
web
表单交互的基本流程大致是:用户访问某个页面,输出表单界面,用户填写表单,提交,程序验证,通过验证或让用户重新填写。流程基本固定,但实现的方式有许多种,在
drupal 中,这整个流程均可以在模块中完成,甚至不用写一行 html 代码。下面开始创建模块。
模块名称:myform。模块名称根据需要自定义,一般来说,不与现有的第三方模块重名。这个模块我们命名为:myform。
实现功能:定义一个页面,生成一个表单,让所有可以提交信息。
权限设置:不做权限验证,所有人均可提交。本教程重点在表单的基本应用,权限部分留待以后。
以下是详细步骤:
第一步:定义模块信息,添加模块信息文件:myform.info
查看代码
打印代码?
第二步:创建数据表,添加模块安装文件:myform.install
1、实现 hook_schema,drupal
为了实现多种数据库的兼容,有自成体系的数据库抽象层,包括创建表、增删查,均有详细接口。此部分留待后文讲述。
查看代码
打印代码?
2、实现 hook_install。在模块被安装时,将调用此钩子。通常,若以 hook_schema 定义了数据表结构,将使用
drupal_install_schema 来完成安装。同时,可以在 hook_install
进行其它操作,比如写入一些默认数据等。
查看代码
打印代码?
3、实现 hook_uninstall。在模块卸载时,将调用此钩子。这并不是必须的,但推荐实现,若你的模块创建了数据表,可调用
drupal_uninstall_schema 删除表。注意:用户禁用模块,并不会调用此钩子。
查看代码
打印代码?
第三步:创建模块主文件,添加模块主文件: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 是一个相当重要的钩子,几乎每个模块都要用到,但不是本篇教程的重点,只做以上简单介绍。
查看代码
打印代码?
第四步:创建表单,创建文件: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。
查看代码
打印代码?
这儿有一个参数: &$form_state,这是 drupal_get_form
自动传递的,其中包含表单 id、token 等信息,若处于验证或提交环节,包含所有用户输入值,即 $_POST。使用
drupal_get_form 也可以传递自定义参数,比如:drupal_get_form('myform_page_form',
$test),那么 myform_page_form 函数则要这样:
查看代码
打印代码?
此处不做深入讨论,回到本教程,创建表单的全部代码如下:
查看代码
打印代码?
接下来是表单验证函数。刚接触 drupal 的朋友可能有这个疑惑,drupal
为什么要把表单的验证和提交环节分开呢,这不是影响效率吗,验证完毕不是可以直接做入库等提交操作吗?实际上,这是为了让表单机制更灵活,假设验证和提交环节不分开,某个模块定义了表单,其它模块也想要验证这个表单,怎么办?验证和提交分离,其它模块可以轻松的通过
hook_form_alter
添加一个验证函数,在该函数中,可阻止表单提交。国内很多程序,均不考虑这些需要,所以,如果要进行二次开发,只有在源代码上进行修改,缺乏灵活性。myform_page_form
表单的验证函数代码如下:
查看代码
打印代码?
以上只验证了长度是否合法,实际应用中,可能还需要验证电子邮件是否合法等。验证通过后,进行提交环节,代码如下:
查看代码
打印代码?
表单成功写入数据库,整个表单的流程就走完了。很简单吧?因为规则不熟悉,可能不明白为什么要这样写,实际上,刚开始做模块开发,只需要知道要这样即可以,不必深究为什么要这样。倘若先拿一本书,务必把每个术语搞清楚,理解透彻,没有实际开发经验,我想还是比较困难的。好读书不求甚解,大概也是这个道理吧。做多了,自然就明白了,可能我是实践主义者。
以上就是本篇教程的全部内容,下一篇将继续研究表单,说说关于文件上传。
启用后,访问 http://www.mysite.com/?q=myform 即可提交表单。
也不例外。drupal 的表单系统相当强大,可以让程序员不写任何 html
代码,完成表单的生成、验证、提交、入库等一系列流程。在模块开发中,几乎都会和表单打交道。
这篇教程是 drupal 表单的基本应用实例,涉及表单的定义、验证、提交等基本环节。
本系列教程,都以 drupal 6 为基础,以模块为载体,每篇教程即为一个模块,以后不再做特殊说明。
web
表单交互的基本流程大致是:用户访问某个页面,输出表单界面,用户填写表单,提交,程序验证,通过验证或让用户重新填写。流程基本固定,但实现的方式有许多种,在
drupal 中,这整个流程均可以在模块中完成,甚至不用写一行 html 代码。下面开始创建模块。
模块名称:myform。模块名称根据需要自定义,一般来说,不与现有的第三方模块重名。这个模块我们命名为:myform。
实现功能:定义一个页面,生成一个表单,让所有可以提交信息。
权限设置:不做权限验证,所有人均可提交。本教程重点在表单的基本应用,权限部分留待以后。
以下是详细步骤:
第一步:定义模块信息,添加模块信息文件:myform.info
查看代码
打印代码?
1 | // $Id$ |
2 | name = myform |
3 | description = 用户反馈表单 |
4 | core = "6.x" |
1、实现 hook_schema,drupal
为了实现多种数据库的兼容,有自成体系的数据库抽象层,包括创建表、增删查,均有详细接口。此部分留待后文讲述。
查看代码
打印代码?
01 |
04 | function 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 | } |
drupal_install_schema 来完成安装。同时,可以在 hook_install
进行其它操作,比如写入一些默认数据等。
查看代码
打印代码?
1 |
4 | function myform_install() { |
5 | drupal_install_schema( 'myform' ); |
6 | } |
drupal_uninstall_schema 删除表。注意:用户禁用模块,并不会调用此钩子。
查看代码
打印代码?
1 |
4 | function myform_uninstall() { |
5 | drupal_uninstall_schema( 'myform' ); |
6 | } |
根据我们的需要,需要定义一个页面,使用 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 |
04 | function 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 | } |
为什么要将表单代码写在另一个文件呢?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 |
5 | function myform_page_form(& $form_state ) { |
6 | } |
自动传递的,其中包含表单 id、token 等信息,若处于验证或提交环节,包含所有用户输入值,即 $_POST。使用
drupal_get_form 也可以传递自定义参数,比如:drupal_get_form('myform_page_form',
$test),那么 myform_page_form 函数则要这样:
查看代码
打印代码?
1 |
7 | function myform_page_form(& $form_state , $test ) { |
8 | } |
查看代码
打印代码?
01 |
05 | function 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 | } |
为什么要把表单的验证和提交环节分开呢,这不是影响效率吗,验证完毕不是可以直接做入库等提交操作吗?实际上,这是为了让表单机制更灵活,假设验证和提交环节不分开,某个模块定义了表单,其它模块也想要验证这个表单,怎么办?验证和提交分离,其它模块可以轻松的通过
hook_form_alter
添加一个验证函数,在该函数中,可阻止表单提交。国内很多程序,均不考虑这些需要,所以,如果要进行二次开发,只有在源代码上进行修改,缺乏灵活性。myform_page_form
表单的验证函数代码如下:
查看代码
打印代码?
01 |
08 | function 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 |
06 | function 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 即可提交表单。
相关文章推荐
- Drupal&nbsp;模块开发基本教程(一)
- Drupal&nbsp;模块开发基本教程(二)
- Drupal&nbsp;模块开发基本教程(三)
- Drupal7 form表单二次开发要点与实例
- Java rmi开发实例 泽0715 新浪博…
- Android开发实例&nbsp;简单拨打电话
- PHPCMS&nbsp;V9构建模块&nbsp;-&nbsp;实例之…
- PHPCMS&nbsp;v9构建模块&nbsp;-&nbsp;实例之…
- Android&nbsp;NFC开发读写NDEF数据实例
- 【转载】Drupal&nbsp;钩子系统实例讲解—…
- magento模块实例开发,前后台开发,表单提交案例
- Drupal7 form表单二次开发要点与实例
- 8&nbsp;Nginx模块开发
- magento中模块开发实例,前后台开发,前台表单提交,页面配置显示
- node.js调用C++开发的模块实例
- iOS开发&nbsp;引用第三方库出现duplicat…
- 【原创】python 使用系统模块…
- 申请开发或发布证书 xcode4.4
- Android开发: 获得某一个类…
- 【转】&nbsp;软件开发人员的作战手册&nbsp;-&nbsp;…