英雄联盟禁止tp:Drupal专业开发指南 第2章 创建一个模块(1) - g089h515r806的专栏 - CSDNBlog

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 19:12:44

创建一个模块(Module

 

  在许多开源的应用中,你可以通过修改源代码来定制你的应用。这通常是一个获得你期望的行为的一种方式,但是在drupal中,一般是不赞成这样做的,它被是做万不得已的一个手段。修改源代码,意味着随着每次Drupal的升级,你必须要做更多的工作---你必须测试以下你的定制代码还想期望的那样工作。代替的,Drupal的设计从一开始便考虑到了模块化和可扩展性。

  Drupal是个精简的并且优雅的用于开发应用的一个框架,它的默认安装通常被称作为Drupal的核心。通过启用新的模块来向核心添加功能,这些模块是一些包含PHP代码的文件,放置在你的Drupal安装路径sites/all/modules的子目录下。现在看一下这个子目录,现在你可以在你的Drupal站点上导航到Administer->Site building->Modules,比较一下子目录下的模块与网页上的模块列表。

 在本章,我们将从头开始创建一个模块;你将学到模块必须遵守的一些标准。我们需要一个真实的目标,所以让我们考虑以下现实中的注释问题。当用户在Drupal网站上浏览内容时,用户可能对内容发表评论(如果管理员开启了评论(comment)模块).但是如果是在一个网页上添加一个注释(一种仅有用户可见得节点类型),那会怎么样?这对于私密的评价内容可能非常有用(我们知道这看起来有些做作,但是现在我们来试暂时忍受一下吧)。

 

创建相应的文件

首先我们要做的是为模块起一个名字,名字“annotate”看起来还是比较合适的简洁并且生动。现在我们需要为它找一个放置的位置。让我们把它放在目录sites/all/modules下面来使它和核心模块区分开来。我们创建一个子目录,而不仅仅是一个annotate.module文件,这是应为在我们的模块发行版本中我们还需要一些其他的文件。比如我们需要一个README.txt文件,用来向其他用户解释我们的模块是做什么的,以及如何使用它,还有一个annotate.info文件用来向Drupal提供一些关于我们模块的信息。准备好了吗?

  我们的annotate.info文件内容如下:

; $Id$

name = Annotate

description = Allows users to annotate nodes.

package = Example

version = "$Name$"

这个文件采用.ini格式,这是一个用于PHP配置文件的简单标准(参看http://php.

net/parse_ini_file)。我们从一个版本管理系统(CVS)的标识符的标签开始,并且为Drupal的网站上模块管理部分提供了相应的名称(name)和描述(description)。模块可以按组来展示,而组的划分是由包(package)决定的;这样,如果我们有3个不同的模块,他们都有package=Example,那么他们将被放在同一个组中。版本的值是另一个CVS的标示标签。如果我们想和其他用户分享这一模块,通过将它放到Drupal的贡献模块库中,这个值将会被自动填充。

 

  注意:你可能在想,为什么我们需要一个单独的.info文件。为什么不在我们的主模块中写一个函数来返回这些元数据呢?这是因为在模块管理页面加载时,它将不得不加载并解析每一个模块,不管有没有启用,这比平时需要更多的内存并且可能超出分配给PHP的内存上限。

通过使用.info文件,信息可以更快速的加载并且使用更少的内存。

 

现在我们准备好创建一个真实的模块了。在你的子目录annotate下面创建一个名为annotate.module的文件。在文件的开始出使用PHP的开始标签和一个CVS标示符标签,并紧跟一个注释:

// $Id$

/**

* @file

* Lets users add private annotations to nodes.

*

* Adds a text field when a node is displayed

* so that authenticated users may make notes.

*/

 

首先,让我们看一下注释的风格。我们从/**开始,在接下来的每一行中缩进一格并以*开头,最后以*/结束。标记@file意味着在接下来的一行是对这个文件要做什么的一个描述。这一行的描述将被这样使用,Drupal的自动文档提取和格式化模块api.module用它来找出这个文件是做什么的。空了一行后,我们为可能检查(并且改进)我们代码的程序员提供了一个更长的说明。注意,我们在这里故意没有使用一个结束标签?>;这对于PHP来说是可选的,如果包含了它,就可能导致文件的尾部空格问题(参看http://drupal.org/node/545)。

 

注意:为什么我们在这里这么详细的讲述每一个细节?这是因为,如果来自世界各地的成千上百的人开发同一个项目的话,如果大家采用一种标准的方式的话,将会节省大量的时间。关于Drupal的代码风格的更详细的内容可以从Drupal的用户手册的“代码标准”一节中找到(http://drupal.org/node/318)。

 

 保存你的文件,访问Administer->Site building->Modules.你的模块将会出现在列表中。多么激动人心啊。

 下面我们要做的就是定义一些设置,这样我们就可以使用一个基于web的表单来选择哪些节点类型我们可以添加注释。这需要两步。首先我们定义一个我们可以访问我们设置的路径。然后我们创建设置的表单。

 

                     实现一个钩子

  回想一下,Drupal是建立在一个钩子的系统之上,有时候称之为回调。在执行的过程中,Drupal询问模块看它们是不是想要做些事情。举例来说,当决定那一个模块负责当前的请求时,它向所有的模块询问是否提供提供相应的路径。通过制造一个所有模块的列表,并且调用每个模块中名为:模块名+_menu的函数,来做这件事。当它遇到我们的annotate模块时,它调用函数annotate_menu(),并向它传递一个参数。这个参数意味着这个模块的相应是否可被缓存。一般情况下,菜单项可以被缓存;我们将在第4章介绍例外情况,这章讲述了Drupal的菜单/回调系统。每一个菜单项是一个联合的数组。下面就是要向我们模块中添加的东西:

/**

* Implementation of hook_menu().

*/

function annotate_menu($may_cache) {

$items = array();

if ($may_cache) {

$items[] = array(

‘path‘ => ‘admin/settings/annotate‘,

‘title‘ => t(‘Annotation settings‘),

‘description‘ => t(‘Change how annotations behave.‘),

‘callback‘ => ‘drupal_get_form‘,

‘callback arguments‘ => array(‘annotate_admin_settings‘),

‘access‘ => user_access(‘administer site configuration‘)

);

}

return $items;

}

此时不要在细节上过于担心。这段代码说,“当用户访问页面http://example.com/?q=admin/settings/annotate时,调用函数drupal_get_form,并向它传递了一个表单ID annotate_admin_settings”。当Drupal完成了向所有的模块询问它们的菜单项时,它将会找到一个菜单以从中选择一个函数用于相应所请求的路径。

  注意,所有将被展示给用户的文本被放在了函数t()中,它将会在字符串翻译时调用。通过对所有的可展示文本使用字符串的翻译函数,这使得本地化你的模块为另一个不同语言时非常方便。

  注意:如果你对于钩子机制很感兴趣的话,参看文件includes/module.inc里面的函数module_invoke_all()。

 

现在你应该清楚我们为什么叫它hoo_menu或者菜单钩子了。Drupal的钩子通过在钩子的名称前加上你的模块名来创建。

 

秘密消息:Drupal的发展很快。一个支持的钩子的完全列表和它们的使用说明可在Drupal的API文档站点(http://api.drupal.org)上找到。

 

              添加特定模块的设置

Drupal有多种不同的节点类型,比如Story和Page。我们想将评论的使用限定在特定的一些节点类型上。为了实现它,我们需要创建一个页面,在这里我们告诉我们的模块那些节点类型我们想评论。向annotate模块添加下面的代码:

/**

* Define the settings form.

*/

function annotate_admin_settings() {

$form[‘annotate_nodetypes‘] = array(

‘#type‘ => ‘checkboxes‘,

‘#title‘ => t(‘Users may annotate these node types‘),

‘#options‘ => node_get_types(‘names‘),

‘#default_value‘ => variable_get(‘annotate_nodetypes‘, array(‘story‘)),

‘#description‘ => t(‘A text field will be available on these node types to make

user-specific notes.‘),

);

$form[‘array_filter‘] = array(‘#type‘ => ‘hidden‘);

return system_settings_form($form);

}

在Drupal中,表单被表示为一个嵌套的树状结构;也就是说,一个数组的数组。这个结构向Drupal的表单呈现引擎(renderingengine)描述了表单是如何表示的。为了可读性,我们将数组中的每一个元素放到单独的一行里面。每一个指示都以”#”开头,它作为数组的键。我们首先声名了表单元素的类型为复选框,这意味着通过使用一个键入的数组来构建一个多选的复选框。我们为表单元素设置一个标题,像平常的一样使用了t()函数。然后我们将选项(options)赋值为node_get_types(‘names‘),它方便的返回了当前Drupal中可用的节点类型的键值数组。函数node_get_types(‘names‘)的输出看起来像这个样子:

‘page‘ => ‘Page‘, ‘story‘ => ‘Story‘

数组的键对应于节点类型在Drupal中的内部名称,而把可读性的名称(显示给用户的)放到右边。如果你启用了一个Savory Recipe模块,数组看起来将像这样:

‘page‘ => ‘Page‘, ‘savory_recipe‘ => ‘Savory recipe‘, ‘story‘ => ‘Story‘

 

  因此,在我们的web表单中,就为page和story两种节点类型生成相应的复选框。下一个指示,#default_value,将是这个表单元素的默认值。由于checkboxes是一个多值的表单元素(即是说,存在多于一个的复选框),所以#default_value的值将会是一个数组。

  #default_value的值值得讨论一下:

variable_get(‘annotate_nodetypes‘, array(‘story‘))

  Drupal允许程序员使用特定的一对函数:varialble_get()和varialble_set()来存储和回显任意一个值。值被存储到了数据库表variables中,并且在处理一个请求的任一时候都是可用的。由于在处理每个请求时都会回显这些值,所以不能用这个方法来存储大数量的数据。但是它是个非常方便的方式用来存储模块的配置属性值。注意我们向方法varialble_get()中传递了一个对于值描述的键(所以我们可以取回来它),和一个默认值。在这种情况下,默认值是一个关于那些节点类型允许注释的数组。这样默认情况下,我们允许评论节点类型Story。

  最后我们提供一个描述,用来告诉站点管理员关于这个域的一些更细节的信息。

现在导航到Administer ? Settings ? Annotate,我们将看到为annotate.module所显示的表单。

  

2-1,为annotate.module生成的配置表单。

 

定义$form[‘array_filter‘]的这行代码看起来有点神秘。不过现在,我们只需要知道,当我们使用settings钩子的存储我们的复选框值的时候,它是必须的,者就可以了。

  仅用了几行代码,我们为我们的模块提供了一个可用的配置表单,它将自动的保存和记起我们的设置。好的,代码中的一行长度适中,但是仍然,这会给你一种使用Drupalde 奇妙感觉。

 

发表于 @ 2007年09月22日 17:03:00|评论(0)|编辑

Drupal专业开发指南 第2章 创建一个模块(1) - g089h515r806的专栏 - CSDNBlog Drupal专业开发指南 第2章 sdfsdf建一个模块(1) - g089h515r806的专栏 - CSDNBlog Drupal专业开发指南 第1章 Drupal工作原理(2)对请求提供服务 计算机核心期刊投稿指南1 - Nicholas黎的专栏 - CSDNBlog 计算机核心期刊投稿指南 - Nicholas黎的专栏 - CSDNBlog GCC for Win32开发环境介绍 - 北斗星君的专栏 - CSDNBlog Effective Java 笔记(七) - ilibaba的专栏 - CSDNBlog Effective Java 笔记(二) - ilibaba的专栏 - CSDNBlog 一个Dijkstra算法的完整Java程序实现,- brokencar的专栏 - CSDNBlog 阅人有术(转载) - icdbow的专栏 - CSDNBlog 酒店业GDS - linyunliang的专栏 - CSDNBlog 《代码大全》读书笔记 - ilibaba的专栏 - CSDNBlog IPD流程概述 - liyonghust的专栏 - CSDNBlog PPT经常用的115个技巧 1- 张艳 的 专栏 - CSDNBlog 从头开始编写操作系统(2) 第1章:介绍 - xiaoxiaoyaya的专栏 - CSDN... web.xml配置的详细说明 - eako的专栏 - CSDNBlog VC 的工程文件说明 - piero_hover的专栏 - CSDNBlog 各类开源软件目录2007 - funson的专栏 - CSDNBlog 推荐引擎:从搜索到发现 - java060515的专栏 - CSDNBlog 十方面经典名录 - 亦风亦尘的专栏 - CSDNBlog C语言陷阱和缺陷zz - 刀目村的专栏 - CSDNBlog apache index dirctory乱码问题 - newman0708的专栏 - CSDNBlog 动 态 语 言 - bobseadream的专栏 - CSDNBlog 软件工程文档模板----一、可行性研究报告 - lihuaidong521的专栏 - CSDNBlog