在本章,你将找到所有的代码小提示和最佳实践,这将使你从 Drupal 开发者中脱颖而出,并帮你摆脱电脑的折磨。
代码规范
Drupal 社区已经达成一致,它的代码基础必须拥有一个标准的外观,从而提高可读性,也使得初学者更容易的学习。社区也鼓励第3方模块的开发者采用这些标准。
行缩进
Drupal 代码缩进使用两个空格,而不是 tab 键。对于大多说编辑器,你都可以设置一个偏好,从而自动的使用 tab 键代替空格,这样你就可以继续使用 Tab 键了 - 如果你习惯使用 tab 键的话。
控制结构
控制结构体是程序中用来控制执行流程的指令,比如条件语句和循环语句。条件语句有 if、else、elseif 和 switch 语句。循环语句有 while、do-while、for 和 foreach。
控制结构体在控制关键字(if、elseif、while、for 等等)和开括号”(”之间应有一个空格,从而将其与函数调用(也使用圆括号)区分开来。”{”应该与关键字位于同一行(而不是自成一行)。
“}”应该自成一行。
不正确的:
if ($a && $b)
{
sink();
}
正确的:
if ($a && $b) {
sink();
}
elseif ($a || $b) {
swim();
}
else {
fly();
}
花括号”{}”一般总是使用的,即便是它们不是必须的时候,为了增强可读性可减少出错的机会。
不正确的:
while ($a < 10)
$a++;
正确的:
while ($a < 10) {
$a++;
}
Switch 语句的格式应该这样:
switch ($a) {
case 1:
red();
break;
case 2:
blue();
break;
default:
green();
}
函数调用
在操作符(=、 <、> 等等)的两边应该各有一个空格,在函数名和函数的开括号”(”之间没有空格。在函数的开括号”(”和它的第一个参数之间也没有空格。中间的函数参数使用逗 号”,”和空格” “分隔的,最后一个参数和闭括号”)”之间没有空格。下面的例子说明了这些要点。
不正确的:
$var=foo ($bar,$baz);
正确的:
$var = foo($bar, $baz);
该规则也存在例外的情况。在一个代码区块中,存在多个相关的赋值语句时,如果能够提高可读性的话,是可以赋值操作符周围插入更多空格的:
$a_value = foo($b);
$another_value = bar();
$third_value = baz();
数组
对于数组,也是使用空格对其每个元素和每个赋值操作符进行分割的。如果数组代码区块跨越了80个字符,那么每个元素都应独立成行。为了提高可读性和维护性,最好都将每个元素独立成行。这样就方便了你来添加或者删除元素。
不正确的:
$fruit['basket'] = array(’apple’=>TRUE, ‘orange’=>FALSE, ‘banana’=>TRUE,
‘peach’=>FALSE);
正确的:
$fruit['basket'] = array(
‘apple’ => TRUE,
‘orange’ => FALSE,
‘banana’ => TRUE,
‘peach’ => FALSE,
);
注意:数组最后一个元素的后面有一个逗号,这不是一个错误,PHP 允许这个语法。放在这里是为了防止犯错,这样开发者就可以方便的在数组列表的最后添加或者删除一个元素。这一规范是允许的,但是不是必须的。
当创建内部的 Drupal 数组时,比如菜单项或者表单定义,总是将每个元素单独成行:
$form['flavors'] = array(
‘#type’ => ’select’,
‘#title’ => t(’Flavors’),
‘#description’ => t(’Choose a flavor.’),
‘#options’ => $flavors,
);
PHP 注释
Drupal 遵循大多数的 Doxygen 注释样式规范。所有的文档区块必须使用下面的语法:
/**
* Documentation here.
*/
除了第一行以外,其它各行在星号(*)前面必须要有一个空格。
注意:Doxygen 是一个能够友好支持 PHP 的文档生成器。它从代码中提取 PHP 注释并生成适合阅读的文档。更多信息,参看 http://www.doxygen.org。
当为一个函数添加说明文档时,文档区块必须紧挨着放在函数前,中间不能存在空行。
Drupal 能够理解下面所列的 Doxygen 构造体;尽管我们能够覆盖其中的大多数,更多关于如何使用它们的信息请参看 Doxygen 的官方站点:
- @mainpage
- @file
- @defgroup
- @ingroup
- @addtogroup (as a synonym of @ingroup)
- @param
- @return
- @link
- @see
- @{
• @}
遵循这些标准的好处是,你可以使用第3方的 API 模块为你的模块自动生成文档。API 模块实现了 Doxygen 文档生成器规范的一个子集,专门针对 Drupal 代码生成文档进行了优化。访问 http://api.drupal.org 你就可以看到这个模块的一个实际使用的例子,而关于 API 模块的更多信息,参看 http://drupal.org/project/api。
文档例子
让我们从头到脚的看一遍一个模块的轮廓,同时将不同类型的文档高亮显示。
模块的第2行(在 <?php 标签之后)应该包含一个 CVS 标签用来追踪文档的版本号:
// $Id$
当代码被提交到 CVS 以及从 CVS 更新代码(CVS 的代码是最新的)时,这一标签将自动被解析和扩展。之后,它将看起来像下面的这样:
// $Id: comment.module,v 1.523 2007/01/31 15:49:23 dries Exp $
在本章后面你将学到更多关于如何使用 CVS 的知识。
在声明函数以前,你需要花点功夫使用下面的格式写一个关于模块能做什么的文档:
/**
* @file
* One sentence description/summary of what your module does
* goes here.
*
* A paragraph or two in broad strokes about your module and how it behaves.
*/
常量
PHP 常量全部都应该大些,可以使用下划线分隔单词。当定义 PHP 常量时,最好能够解释一下它们是用来做什么的,如下面的代码片段所展示的这样:
/**
* These values should match the IDs in the ‘role’ table.
*/
define(’DRUPAL_ANONYMOUS_RID’, 1);
define(’DRUPAL_AUTHENTICATED_RID’, 2);
函数文档
函数文档应该使用下面的语法:
/**
* Short description.
*
* Longer description goes here.
*
* @param $foo
* A description of what $foo is.
* @param $bar
* A description of what $bar is.
* @return
* A description of what this function will return.
*/
function name_of_function($foo, $bar) {
…
}
让我们看一个来自于 Drupal 内核 book.module 中的一个例子:
/**
* Format $content as a standalone HTML page. Useful for exporting an HTML
* version of the book.
*
* @param $title
* Plain text title of the page.
* @see theme_book_navigation
* @return
* A standalone HTML page.
* @ingroup themeable
*/
function theme_book_export_html($title, $content) {
…
}
在前面的例子中有一些新的 Doxygen 结构体
@see 告诉你要引用哪些函数。
@ingroup 将一组相关的函数联系到了一起。在我们的例子中,它创建了一组 themeable(可主题化)函数。你可以创建任何你想要的组名。比较常用的值有:database、themeable 和 search。
提示:你可以在 api.drupal.org 查看一个特定组的所有函数。例如,可主题化(themeable)的函数在 http://api.drupal.org/api/5/group/themeable 全列出来了。
通过程序来检查你代码的样式
在你的 Drupal 根目录下的 scripts 子目录里面,你可以找到一个名为 code-style.pl 的 Perl 脚本,它用来检查你的 Drupal 代码样式。下面讲述如何使用这个脚本。
首先,修改文件的权限从而使它能被执行;否则,你将得到一个”Permission denied(没有相关权限)”的错误。使用 chmod 通过命令行就可以做到这一点,如下所示:
$ cd scripts
$ ls -l
-rw-r-r- 1 mathias mathias 4471 Oct 23 21:10 code-style.pl
$ chmod 744 code-style.pl
$ ls -l
-rwxr-r- 1 mathias mathias 4471 Oct 23 21:10 code-style.pl
Windows 用户不用修改文件的权限,但是在你运行 code-style.pl 以前一定要先把 Perl 安装了。
通过将模块或者其它要评估的文件的位置传递给 code-style.pl,你就可以执行这个脚本了。下面的例子说明了执行脚本的命令:
$ ./code-style.pl ../modules/node/node.module
程序的输出将采用下面的格式:
line number : ‘error’ -> ‘correction’ : content of line
例如,下面的脚本告诉我们,我们需要在 foo.module 的30行中赋值操作符(=)周围添加空格:
foo.module30: ‘=’ -> ‘ = ‘ : $a=1;s
注意:一定要清楚优点和不足。这一脚本做的很不错,但它还没有十全十美,所以你需要细心的评估每一个报告。
使用 egrep 来查找代码
egrep 是一个 Unix 命令,用来在文件中搜索匹配给定正则表达式的位置。不,它不是一个飞鸟(那是 egret 白鹭)。如果你是一个 Windows 用户并且想差试一下下面所列的例子,你可以通过安装一个已编译的版本(参看 http://unxutils.sourceforge.net)或者安装 Cygwin 环境(http://cygwin.com),来使用 egrep。否则,你只能使用操作系统内置的搜索功能而不是 egrep。
当你需要在 Drupal 内核中查找钩子实现时,当查找错误消息生成的位置时,以及其他一些情况时,egrep 都是一个很方便的工具。让我们看一些在 Drupal 根目录下使用 egrep 的例子:
$ egrep -rl ‘hook_load’ .
./modules/forum/forum.module
./modules/poll/poll.module
在前面的情况下,我们从当前目录(.)在 Drupal 文件中递归的搜索(-r)包含 hook_load 的实例,并将匹配实例的文件名打印出来(-l)。现在看下面的例子:
$ egrep -rn ‘hook_load’ .
./modules/forum/forum.module:228: * Implementation of hook_load().
./modules/poll/poll.module:281: * Implementation of hook_load().
这里,我们在我们 Drupal 文件中递归的搜索带有字符串”hook_load” 的实例,并将它们出现的位置以及行号打印出来。我们可以对搜索结果进一步搜索。在接下来的例子中,我们在前面例子的搜索结果集中搜索单词”poll”出现的情况:
$ egrep -rn ‘hook_load’ . | egrep ‘poll’
./modules/poll/poll.module:281: * Implementation of hook_load().