公告这个是dghabc用于学习drupal的站点,暂时没有开放用户注册,但所有人都可以发表评论.您的评论就是对我最好的支持. |
表单系统表单系统是drupal开发中比较重要的内容之后,我们与网页进行交互时,都要用到表单来进行,表单系统也是drupal比较难以掌握的一个内容,其中牵涉到大量的其他内容,如theme,ahah等,我把这几天看的内容先给记下来.表单系统的处理过程: 这个图原书上是错的,这个是从官上下的这订正图
三个很重要的变量$form_id,$form,$form_state, $form_id是通过drupal_get_form(‘参数'),这个就是form_id, $form是一个结构化的数组,用来描述表单的内容.(其实就是你设置表单的数组,还有加了很多其他内容.) $form_state是表单处理完成之后的内容.其中$form_state[‘values'][‘名称']是可以引用表单处理之后的内容.
表单系统的一个优点是,它尽力去保证被提交的表单是由Drupal真正创建的。这主要是为了安全性和防止垃圾信息的提交。为了达到这一点,Drupal为每一个Drupal安装都设置了一个私钥,Drupal将基于私钥生成一个随机的令牌作为隐藏于发送到表单中。当表单提交时,会对令牌进行测试。相关背景信息请参看drupal.org/node/28420。令牌只在登录用户中适用,因为匿名用户的页面通常会被缓存起来,这样它们就没有一个唯一的令牌了。
一个包含了当前表单ID的隐藏域作为表单的一部份被发送给浏览器。该ID一般对应于定义表单的函数,它也是方法drupal_get_form()的第一个参数。例如函数user_register()定义了用户注册表单,它的调用方式如下:$output=drupal_get_form('user_register');
接着,调用element_info()。它将触发所有实现了钩子函数hook_elements()的模块上的钩子函数。在Drupal核心内部,标准表单元素,比如单选按钮和复选框,都定义在system.module中的钩子函数hook_elements()中。当模块需要定义他们自己的元素类型时,就需要实现这个钩子。在以下几种情况中,你可能需要在你的模块中实现hook_elements():你想要一个特定的表单元素类型时,比如一个可在预览节点时展示图像缩略图的图像上传按钮;或者,你想通过定义更多的属性来扩展已有的表单元素时。
通过将表单的属性#validate设置为一个数组,其中函数名为键,一个数组作为值,从而为表单指定一个验证函数。在调用验证函数时,后面数组中的任何数据将被作为参数传递给验证函数。可以使用下面的方式定义多个验证器:
与前面的验证函数类似,通过将表单的属性#submit设置为一个数组,
现在表单被传递到了函数form_builder()中,该函数迭代的处理表单树,并添加必须的标准值。form_builder($form_id, $form, &$form_state)
在函数form_builder()中,每次遇到$form树中的一个新的分支时(例如,一个新的字段集或表单元素),它都寻找一个名为#after_build的可选属性。该属性是一个数组,一旦当前表单被构建完成以后,就会立即调用数组中的函数。当整个表单被构建完成以后,将会调用可选属性$form[‘#after_build']中定义的函数。所有的#after_build函数都接收$form_id和$form_values作为参数。
我们将在稍后讨论这一点(参看本章后面的"验证表单"部分)。现在我们将假定表单是第一次出现在这里。
如果已将form[‘#theme']设置为了一个已存在的函数,Drupal只需要简单的使用该函数就可以了。如果没有设置,模板注册表将自动去寻找主题,如果找到的话,会分配给form[‘#theme']这个过程是通过form_id去寻找的,例如对于taxonomy_overview_terms表单,drupal会自动去寻找theme_ taxonomy_overview_terms()函数,当然这些函数也可以在模板系统中被重写,看一下第8章的模板系统内容.
剩下的最后一件事就是将表单从结构化数组转化为HTML。但是在这以前,模块还有最后一个机会来修改表单。这对于跨页面向导表单或者其它需要在最后时刻修改表单的方式,将会非常有用。此时将会调用属性#pre_render中定义的任何函数,函数参数有$form_id和$form。1.看是否定义了#children元素(与"为该元素已经生成内容"同义);如果没有,这样显示表单树中该节点的孩子:
2.如果该元素还没有被打印出来,调用缺省的theme,如textfield字段,则调用theme_textfield(),这些函数在includes/form.inc文件中,如果没有为该元素设置#type属性,那么将其默认为markup。3.如果生成的元素中包含#post_render属性,则分别调用这些函数, post_render函数必须返回生成的最终内容。4.在内容前面追加#prefix,在后面追加#suffix,并将它从函数中返回。该递归反复执行的结果就是为表单树的每一层次生成HTML。例如,在一个表单包含一个字段集,而字段集又包含两个字段,那么该字段集的#children元素将包含两个字段的HTML,而表单的#children元素将包含整个表单的HTML(其中包括字段集的HTML)。生成的HTML将会返回给函数drupal_get_form()的调用者。这就是显示表单所要做的全部工作!
现在让我们看一下需要检查表单是否被提交的情景。决定一个表单是否已被提交有以下几点:$_POST是否为空,$_POST['form_id']中的字符串是否匹配表单的ID或者$form['#base']的ID。如果都匹配,那么Drupal将开始验证了Token ValidationBuilt-in ValidationElement-Specific ValidationValidation Callbacks
如果验证通过了,那么就该把表单和表单中的值传递到一个函数中,该函数将做一些实际逻辑处理作为表单提交的结果。事实上,可以有多个函数用来处理表单,这是由于#submit属性可以包含多个键值对,其中键为要调用的函数的名称,值为一个用来为函数传递参数的数组(另外,表单ID和表单值,分别为函数的第一第二参数)。
处理表单的函数的返回值是一个为用户重定向的Drupal路径,比如node/1234。如果#submit属性中有多个函数,那么将会使用最后一个函数的返回值。如果函数没有返回一个Drupal路径的话,那么用户将回到原来的页面(也就是,$_GET['q']的值)。从最后一个函数返回FALSE将阻止重定向。可以通过在表单中定义#redirect属性来覆盖函数的返回值,比如$form['#redirect']='node/1'或$form['#redirect']=array('node/1',$query_string,$named_anchor)。实际的重定向由drupal_goto()负责,它为Web服务器返回一个定位(Location)头部信息。 |

最新评论