任何合作的專案都需要一致性和穩定性才能保持它的強壯。
編寫這些準則的目的是為所有的Moodle代碼提供一個努力的目標。有一些比較老的已經存在的代碼在極少的方面尚未達標,但它們最終將會被修正。所有新的代碼都必須盡可能地遵守這些準則。
1. 所有代碼檔應當使用 .php 作為副檔名。
2. 所有範本檔應當使用 .html 作為副檔名。
3. 所有文字檔案應當使用Unix風格的文本格式(多數的文本編輯器都有這個選項)。
4.
所有php標記都必須是“完整”標記,譬如<?php ?> ... 而不是如<? ?>的“短”標記。
5. 所有已經存在的版權聲明應當被保留。如果有必要,您可以加入自己的。
6. 每個檔都應當包含主config.php文件。
7. 每個檔都應當檢查用戶的身份是否正確,可以使用函數require_login()和isadmin()、isteacher()、iscreator()或者isstudent()。
8. 所有訪問資料庫的操作都應當使用lib/datalib.php中的函數――這樣可以相容更多的資料庫伺服器。所有的事情都應當是可以用這些函數來完成的,如果遇到必須要寫SQL代碼的情況,請記住這些代碼應當是跨平臺的,且僅僅對您代碼中的特定函數(通常在一個lib.php檔中)有效,且代碼中用注釋進行明確說明。
9. 不要建立和使用標準總體變數$CFG、$SESSION、$THEME和$USER之外的總體變數。
10. 所有變數都應當被初始化或者至少在使用前用isset()或empty()等函數進行檢測。
11. 所有字串都應當可翻譯――在"lang/en"目錄中創建新的文字檔案,字串應當使用簡潔的英文小寫名稱,並通過函數get_string()或print_string()來取得。
12.
所有幫助檔應當可翻譯――在"en/help"目錄中創建文字檔案並且通過helpbutton()函數來調用它們。
如果需要上傳一個幫助檔:
o
對於小的修改,舊的翻譯檔仍然可以繼續使用時,可以直接進行修改,但您應當通知translation@moodle.org
o 對於大的修改,應當創建新的檔,新檔的檔案名是在原檔案名的末尾添加一個數字,並在以後逐漸增加(如filename2.html),這樣翻譯人員就可以方便地知道檔有了一個新的版本。很顯然,新的代碼和幫助索引檔都必須修改以指向新版本的檔。
13. 從流覽器發來的資訊(以GET或POST形式發送)都應用了magic_quotes(無論PHP的設置如何),因此直接將它們插入到資料庫中是安全的。所有其他的原始資料(來自檔或資料庫的)都必須在插入資料庫前使用addslashes()進行預處理。
14.
重要的:Moodle中所有的文本,特別是用戶提供的文本,都必須使用format_text()函數來輸出。這樣就可以確保文本已經正確地過濾。
我知道,如果您已經習慣了一種編碼風格而我卻讓您改變它是有一點討厭的,但比較而言,這比日後所有人都需要去搞清混合風格的Moodle代碼要好一些。對於人們使用的任何編碼風格都有很多支援和反對的意見,但現在正在使用的風格已經存在了,因此請堅持下去。
1. 縮進應當是4個連續的空格。絕對不要使用跳位字元。
2.
變數名應當是容易理解、有含義的小寫英文單詞。如果確實需要兩個或以上的單詞,請把它們連在一起,但要保持名稱盡可能短。對於陣列物件,請使用複數名稱。
好的: $quiz
好的: $errorstring
好的: $assignments (用於陣列)
好的: $i (僅用於小型迴圈)
壞的: $Quiz
壞的: $aReallyLongVariableNameWithoutAGoodReason
壞的: $error_string
3.
常量應當總是大寫的,並總是以模組的名稱作為首碼。單詞之間應當用下劃線分隔。
define("FORUM_MODE_FLATOLDEST", 1);
4. 函數名稱應當是簡單的英文小寫單詞,且總是以模組名作為首碼以防止模組之間的衝突。單詞之間以下劃線分隔。變數如果可能應當總有合理的缺省值。注意在函數名和其後的括弧之間沒有空格。
function forum_set_display_mode($mode=0) {
global $USER, $CFG;
if ($mode) {
$USER->mode = $mode;
} else if (empty($USER->mode))
{
$USER->mode = $CFG->forum_displaymode;
}
}
5.
語句塊必須總是使用大括弧(即便是只有一行)。Moodle使用如下風格:
if ($quiz->attempts) {
if ($numattempts
> $quiz->attempts) {
error($strtoomanyattempts, "view.php?id=$cm->id");
}
}
6. 字串應當盡可能用單引號定義以提高速度。
$var = 'some text without any variables';
$var = "with special characters like a new line n";
$var = 'a very, very long string with a '.$single.' variable in it';
$var = "some $text with $many variables $within it";
7.
實用的注釋應當盡可能填寫,用以解釋代碼流程和函數與變數的功能。
o 每個函數和類都應該使用流行的phpDoc格式編寫,以便自動生成代碼文檔。
o
內嵌注釋應使用 // 風格,並且整齊佈局,使其能融入代碼中並和代碼對齊。
/**
* The description should be first, with asterisks laid out exactly
* like this example. If you want to refer to a another function,
* do it like this: {@link clean_param()}. Then, add descriptions
* for each parameter as follows.
*
* @param int $postid The PHP type is followed by the variable name
* @param array $scale The PHP type is followed by the variable name
* @param array $ratings The PHP type is followed by the variable name
* @return mixed
*/
function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {
if (!$ratings) {
$ratings
= array(); // Initialize the empty array
if ($rates = get_records("forum_ratings",
"post", $postid)) {
// Process each rating in turn
foreach
($rates as
$rate) {
....etc
8.
換行可以被大方地使用——把東西分散開看起來會比較清楚。一般情況下,在花括弧和普通命令之間應當有一個換行符,但在花括弧和變數或函數之間可以沒有換行符:
foreach ($objects
as $key => $thing) {
process($thing);
}
if ($x == $y) {
$a =
$b;
} else if ($x == $z) {
$a =
$c;
} else {
$a =
$d;
}
1. 每個表格都必須有一個自增的id欄位(INT10)作為主鍵。
2.
包含著模組中資料實例的主表格必須和模組同名(譬如widget),並且至少包含如下欄位:
o id - 如上一條所述
o
course - 每個實例所屬的課程id
o name - 每個實例的完整名稱
3.
與模組相關的其他表格的命名規則是:如果它包含的資訊是關於“things”的,則它的名字應當是widget_things(注意採用複數形式)。
4. 欄位名稱應當簡短,與變數名的規則相同。
5.
在可能的情況下,包含著對其他表格(如widget)引用的欄位應當命名為widgetid。(注意這是個新約定,有一些老的表格並未遵守)
6. 布林欄位應當使用小整數類型(如INT4)並存儲為0或1,這樣就可以在需要時擴展它。
7. 多數的表格應當有一個timemodified欄位(INT10),並用PHP的time()函數取得的當前時間戳來更新它。
1. 不要依靠“register_globals”。每個變數必須在每個原始檔案裏正確初始化。變數的來源必須顯而易見
2.
初始化所有的陣列和物件,即使它是空的。$a = array()
或$obj = new stdClass();
。
3.
不要使用optional_variable()
函數。使用optional_param()
函數來替代。根據資料類型選擇正確的PARAM_XXXX值。使用set_default()
函數檢查和設置變數的可選值。
4.
不要使用require_variable()
函數。使用required_param()
來替代。根據資料類型選擇正確的PARAM_XXXX值。
5.
不要使用$_GET
、$_POST
或$_REQUEST
。根據您的需要使用更合適的required_param()
或optional_param()
6.
檢查一個動作時,不要使用像if (isset($_GET['something']))
這樣的代碼。可以使用諸如:$something = optional_param( 'something','',PARAM_ALPHA )
,並且用empty()
函數或(如果'empty'也是一個合法值)isset_param()
函數測試
7.
在任何可能的情況下,把您所有的required_param()
、optional_param()
和其他的變數初始化一起放在每個文件的開頭,這樣它們會更容易被找到。
8.
使用“sesskey”機制保護表單處理函數不被攻擊。簡單示例:當生成表單的時候,要包含<input
type="hidden" name="sesskey" value="<?php echo
sesskey(); ?>" />
。使用表單時用if (!confirm_sesskey()) {error('Bad Session Key');}
檢查。
9.
所有檔案名必須用clean_filename()
函數“過濾”,但如果已經適當地使用required_param()
或optional_param()做了此項工作,則不必如此
10.
再把任何從資料庫讀出的資料寫回之前,必須先用addslashes()
處理。一個完整資料物件可以用addslashes_object()
一次性完全處理完畢。
11.
在任何可能的情況下,存入資料庫的資料必須來自POST
資料(也就是來自表單的資料),而不能來自GET
資料(也就是來自URL的資料)。
12.
如果能避免的話,不要使用來自$_SERVER
的資料。它會給移植性帶來問題
13.
在其他地方沒有做的情況下,確保所有寫入資料庫的資料已經被clean_param
函數處理,並且針對資料類型,使用了恰當的PARAM_XXXX。
14. 如果您編寫了自定義的SQL代碼,請確保它是正確的。尤其小心在數值周圍不要丟失引號,這可能會帶來SQL“注入”漏洞。
15. 每個檔內都要檢查它使用的所有資料(尤其是寫到資料庫的資料)的合法性。不要期盼或依賴其他地方已經檢查了。
16. 被其他檔包含的代碼塊應當有確切定義的PHP結構(例如類的聲明、函數定義等)——直接執行的代碼塊建議使用變數時不要初始化。
Version: $Id: coding.html,v 1.3 2008/07/27 16:28:41 kiang Exp $