縮進與空白字符(Indenting and Whitespace)
使用 2 個空格而不使用 tab 鍵進行代碼縮進(notepad++, Eclipse 等編輯器均支持此項配置);
行尾不應該有空白字符
應使用 \n (Unix換行符),而不是 \r\n (Windows 換行符)
所有文件均應以一個空行結尾
運算符(Operators)
所有二元運算符(二個值之間的運算符),如 +, -, =, !=, ==, > 等等,在運算符兩端均需留有一個空格,如應該使用 $foo = $bar 而不是 $foo=$bar。
所有一元運算符(只操作一個值班的運算符),例如 ++,在值與運算符之間則不應加入空格
轉型(Casting)
在 (type) 與要轉型的變量之間應加入一個空格,如 (int) $mynumber.
控制結構(Control Structures)
控制結構包含 if, for, while, switch 等等,下面是一個簡單的 if 語句結構示例:
復制代碼 代碼如下:
if (condition1 || condition2) {
action1;
}
elseif (condition3 && condition4) {
action2;
}
else {
defaultaction;
}
(Note: 不要使用 "else if" -- 總是使用 elseif.)
控制語句的關鍵詞與左邊括號之間應該有一個空格,以此來與函數調用進行區分。
即使在大括號是可選的情況下,也應當總是使用大括號。這樣可以加強代碼的可讀性以及減少因嵌套帶來的邏輯錯誤。
switch 語句結構示例:
復制代碼 代碼如下:
switch (condition) {
case 1:
action1;
break;
case 2:
action2;
break;
default:
defaultaction;
}
do-while 語句結構示例:
do {
actions;
} while ($condition);
行長度與封裝(Line length and wrapping)
通常情況下,每行代碼的長度不應超過80個字符
以下情況,行長度可超過80個字符:當行內包含過長的函數名稱、函數/類定義、變量聲明等
為方便閱讀和理解,控制結構的行長度可超過80個字符
復制代碼 代碼如下:
if ($something['with']['something']['else']['in']['here'] ==
mymodule_check_something($whatever['else'])) {
...
}
if (isset($something['what']['ever']) && $something['what']['ever'] > $infinite
&& user_access('galaxy')) {
...
}
// Non-obvious conditions of low complexity are also acceptable, but should
// always be documented, explaining WHY a particular check is done.
if (preg_match('@(/|\\)(\.\.|~)@', $target) && strpos($target_dir, $repository)
!== 0) {
return FALSE;
}
控制條件(condition)不應該寫作多行
控制條件應該適當拆分以便於閱讀和理解,編寫代碼時要避免以下情形:
復制代碼 代碼如下:
// DON'T DO THIS!
if ((isset($key) && !empty($user->uid) && $key == $user->uid) || (isset($user-
>cache) ? $user->cache : '') == ip_address() || isset($value) && $value >= time()))
{
...
}
將控制條件進行拆分,不僅便於閱讀,同時也方便添加注釋讓人知道為何進行這樣的條件判斷
復制代碼 代碼如下:
// Key is only valid if it matches the current user's ID, as otherwise other
// users could access any user's things.
$is_valid_user = (isset($key) && !empty($user->uid) && $key == $user->uid);
// IP must match the cache to prevent session spoofing.
$is_valid_cache = (isset($user->cache) ? $user->cache == ip_address() : FALSE);
// Alternatively, if the request query parameter is in the future, then it
// is always valid, because the galaxy will implode and collapse anyway.
$is_valid_query = $is_valid_cache || (isset($value) && $value >= time());
if ($is_valid_user || $is_valid_query) {
...
}
函數調用(Function Calls)
調用函數時,函數名與左括號之間沒有空格,除最後一個參數外,每個參數後的 , 都應跟上一個空格,如:
$var = foo($bar, $baz, $quux);
如之前所說,等號兩邊應該各有一個空格。當有一系列相關語句時,出於可讀性的考慮,可以適當增加空格的數量,如:
$short = foo($bar);
$long_variable = foo($baz);
函數聲明(Function Declarations)
包含默認值的參數應當放在最後,當函數擁有返回值時,盡量返回便於理解的值:
復制代碼 代碼如下:
function funstuff_system($field) {
$system["description"] = t("This module inserts funny text into posts randomly.");
return $system[$field];
}
類構造器調用(Class Constructor Calls)
當調用不帶參數的類構造器時,始終包含括號
$foo = new MyClassName();
帶參數的類構造器
$foo = new MyClassName($arg1, $arg2);
如果使用變量做為類名,需先為變量賦值,然後才調用類構造器:
復制代碼 代碼如下:
$bar = 'MyClassName';
$foo = new $bar();
$foo = new $bar($arg1, $arg2);
數組(Array)
數組的值之間應使用空格分隔,賦值操作符號(=>)左右也應包含空格:
$some_array = array('hello', 'world', 'foo' => 'bar');
當聲明數組的字符長度超過80個字符(通常在構造表單和菜單時),應該將各元素分行、縮進編寫:
復制代碼 代碼如下:
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#size' => 60,
'#maxlength' => 128,
'#description' => t('The title of your node.'),
);
注意:最後一個數組元素末尾有一個逗號,這並不是手誤,而是避免有新元素加入到最後之後因缺少逗號而出現解析錯誤。(從某種程度上來講,在最後一個數組元素末尾加上逗號是一種推薦的做法,甚至在向drupal.org提交代碼時,一些代碼規范檢測腳本會因為最後一個元素沒有添加逗號而出現警告提示。)
引號(Quotes)
Drupal 對於單引號和雙引號的使用並沒有很強硬的標准,只需在同一模塊內保持用法的統一即可。
使用單引號的效率要高於雙引號,因為解析器不需要到引號之間查找變量。以下是使用雙引號的兩種情況:
引號中間帶有變量,如"<h2>$header</h2>"
引號中間帶有單引號,使用雙引號可避免對單引號的轉義 "He's a good person." 當然也可以使用單引號,但 .pot 解析器不能很好的處理這種情況,而且看起來怪怪的'He\'s a good person.'
字符串連接(String Concatenations)
在點與要連接字符串之間需要加入空格以加強代碼可讀性:
如果只是簡單地連接變量,可以使用雙引號
使用連接賦值符(.=)時,需要在符號兩側預留空格
注釋(Comment)
注釋規范單獨在 Doxygen及注釋格式規范頁面 討論
引入代碼(Including Code)
任何無條件引用文件的情況下,使用 require_once(), 任何有條件引用文件的情況,則使用 include_once(). 這兩條語句都會保證文件只被引入一次。
當從當前目錄或子目錄引入代碼時,始終以點路徑開頭
include_once ./includes/mymodule_formatting.inc
在 Drupal 7 及更新版本中,使用 DRUPAL_ROOT 常量:
require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc');
PHP 代碼標簽(PHP Code Tags)
始終使用<?php ?>來界定PHP代碼而不使用要<? ?>。這是為了遵循Drupal規范,同時也便於代碼在其它系統和平台中被引用。
自 Drupal 4.7 開始,最後的 ?> 都故意被忽略不寫,原因如下:
移除它可以避免在文件末尾出現空白字符,這些空白字符可能導致“文件頭已發送(header already sent)”錯誤,XHTML/XML驗證錯誤,及其它問題
PHP 官方說明 結尾的PHP界定符是可選項
PHP.net 自身也移除了文件末尾的界定符(如 prepend.inc )
分號(Semicolons)
PHP 語言要求除了代碼塊以外,大多數行尾都要跟上分號。Drupal 代碼規范同樣有此要求,並且對於代碼塊也是如此。以下是一個單行代碼塊的示例:
-- YES
-- NO
示例 URL(Example URL)
使用 example.com 表示所有示例 URLs
命名規范(Naming Conventions)
函數與變量(Functions and Variables)
函數與變量名稱應該使用小寫字母,且單詞之間使用下劃線分隔。函數應該使用模塊組/模塊名稱作為前綴,以避免與不同模塊間的沖突。
持久變量(Persistent Variables)
持久變量是指通過 variable_get()/variable_set() 函數取得和設置的變量,變量名稱應該使用小寫字母,且單詞之間使用下劃線進行分隔。持久變量也應該使用模塊組/模塊名稱作為前綴,以避免與不同模塊間的沖突。
常量(Constants)
常量始終要求使用全大寫字母,且單詞之間使用下劃線進行分隔。(包括PHP內置常量 TRUE, FALSE, NULL)
模塊中定義的常量需始終使用大寫的模塊名稱作為前綴。
在 Drupal 8 及之後,應使用 const 關鍵詞代替 define() 函數來定義常量,因為效率更高
注意 const 不能用於PHP表達式,因此在條件判斷和非字面值(non-literal value ???)時,還是應當使用 define() 函數
全局變量(Global Variables)
定義全局變量時,應當使用下劃線加模塊/主題名稱開頭
類(Class)
類名應使用駝峰式命名(即單詞首字母大寫)
類中的方法(函數)和屬性(成員變量)應使用首字母小寫的駝峰式
定義訪問權限時,使用 protected 而代替 private,從而其它的類可以在必要時擴展和更新方法。Protected 和 public 函數和變量不應以下劃線開頭。
更多關於 面向對象的編碼規范
文件名(Filename)
所有文檔文件都應加上 .txt 後綴,以便於 Windows 用戶查看。同時,所有文件名稱應該全部大寫,而文件後綴應該全部小寫。
如 README.txt, INSTALL.txt, TODO.txt, CHANGELOG.txt 等等。
輔助模塊及工具
Coder 模塊:可以遵循部分以上代碼規范,對代碼進行審查及修改建議
Drupal Code Sniffer :代碼規范檢測工具
PAReview.sh :還處理沙盒中的代碼規范檢測腳本,幾乎嚴格遵守以上所有代碼規范並給出修改建議。