1. 程式人生 > >騰訊PHP開發規範v1.0

騰訊PHP開發規範v1.0

1引言
1.1定義及縮略語
縮略詞 說明
海豹平臺 運維中心提供的研發平臺,提供框架、公共基礎元件、公共業務元件加速業務的日常研發工作
1.2參考文件
海豹平臺WIKI:http://wiki.seals.webdev.com/
1.3目的
本規範由程式設計原則組成,融合並提煉了開發人員長時間積累下來的成熟經驗,意在幫助形成良好一致的程式設計風格。以達到事半功倍的效果,如果有需要本文件會不定期更新。
1.4適用範圍
如無特殊說明,以下規則要求完全適用於基於海豹平臺框架開發的應用,同時也可大部分適用於部門其他PHP專案。
1.5標準化作用
當一個軟體專案嘗試著遵守公共一致的標準時,可以使參與專案的開發人員更容易瞭解專案中的程式碼、弄清程式的狀況。使新的參與者可以很快的適應環境,防止部分參與者出於節省時間的需要,自創一套風格並養成終生的習慣,導致其它人在閱讀時浪費過多的時間和精力。而且在一致的環境下,也可以減少編碼出錯的機會。
缺陷是由於每個人的標準不同,所以需要一段時間來適應和改變自己的編碼風格,暫時性的降底了工作效率。從使專案長遠健康的發展以及後期更高的團隊工作效率來考慮暫時的工作效率降低是值得的,也是必須要經過的一個過程。標準不是專案成功的關鍵,但可以幫助我們在團隊協作中有更高的效率並且更加順利的完成既定的任務。

1)程式設計師可以瞭解任何程式碼,弄清程式的狀況
2)新人可以很快的適應環境
3)防止新接觸PHP的開發出於節省時間的需要,自創一套風格並養成終生的習慣
4)防止新接觸PHP的開發一次次的犯同樣的錯誤
5)在一致的環境下,可以減少犯錯的機會
2目錄結構規範
2.1框架路徑
框架引用路徑必須採用絕對路徑,託管的開發、測試和正式環境必須為:
/data/php/framework
2.2應用目錄結構
應用需要嚴格參考以下目錄安排程式碼位置:
webroot/
index.php Web 應用入口指令碼檔案
index-test.php 功能測試使用的入口指令碼檔案
assets/ 包含公開的資原始檔
css/ 包含 CSS 檔案
images/ 包含圖片檔案
themes/ 包含應用主題
protected/ 包含受保護的應用檔案
modc 命令列指令碼
modc.bat Windows 下的命令列指令碼
modc.php 命令列 PHP 指令碼
commands/ 包含自定義的 ‘modc’ 命令
components/ 包含可重用的使用者元件
config/ 包含配置檔案
controllers/ 包含控制器的類檔案
SiteController.php 預設控制器的類檔案
extensions/ 包含第三方擴充套件
messages/ 包含翻譯過的訊息(i8n相關)
models/ 包含模型的類檔案
runtime/ 包含臨時生成的檔案
tests/ 包含測試指令碼
views/ 包含控制器的檢視和佈局檔案
layouts/ 包含佈局檢視檔案
main.php 所有檢視的預設佈局
site/ 包含 ‘site’ 控制器的檢視檔案
system/ 包含系統檢視檔案

2.2.1配置config
存放應用配置目錄,具體參考WIKI人口指令碼
2.2.2控制器controllers
存放控制邏輯的類目錄,具體參考WIKI控制器
2.2.3模型models
存放模型定義的類目錄,具體參考WIKI模型
2.2.4檢視views
存放檢視檔案的目錄,具體目錄參考WIKI檢視
2.2.5國際化messages
存放國際化定義檔案的目錄
2.2.6元件components
存放元件的類目錄,具體目錄參考WIKI元件
2.2.7命令commands
存放Console命令的類目錄,具體目錄參考WIKI之Cli使用
2.2.8臨時目錄runtime
目錄許可權777,可用於存放臨時生成的檔案。
2.3路徑別名
1)system: 表示平臺框架目錄,預設為/data/php/framework。
2)webroot: 表示入口指令碼檔案所在的目錄,一般為應用的根目錄。
3)application: 表示應用的基礎目錄,一般為webroot/protected。
4)ext: 表示包含了所有第三方擴充套件的目錄,一般為webroot/protected/extensions。

通過使用 Mod::getPathOfAlias(), 別名可以被翻譯為其相應的路徑。例如:
system.core.web.CController 會被翻譯為 /data/php/framework/core/web/CController。
2.3.1型別匯入
使用別名可以很方便的匯入類的定義,如匯入webroot/protected/components/Controller

Mod::import(‘application.components.Controller’);

同樣可以使用目錄匯入

Mod::import(‘application.components.*’);

3PHP編碼規範
3.1標籤
PHP程式可以使用<?php ?>或<?= ?>來界定 PHP 程式碼,在HTML頁面中嵌入純變數時,可以使用<?= ?>這樣的形式,不可使用其他的標籤變種。
純PHP類檔案,檔案最後一個?>省略。
3.2編碼
PHP程式碼必須只使用不帶BOM的UTF-8。
3.3註釋
1)單行註釋:在語句結尾用雙反斜槓”// “註釋
2)多行註釋:多行注視以”/”或“/**”符號開頭,以”/ “符號作為註釋結束符。

需要生成文件的註釋必須是以“/”開頭,以“*/”結尾。主流的IDE開發工具(如Eclipse,Zend)會用不同的顏色來區分下面的幾種註釋。
3.3.1檔案註釋
/

*(簡述,用在索引列表中)
*

  • 詳細的功能描述(可略)
  • @copyright Copyright© 2013, 公司名或作者名
  • @author ${AUTHOR}
  • @version $Id: ${FILE_NAME}, v ${VERSION} ${TIME} ${AUTHOR} Exp $

/
3.3.2類註釋
/
*
*(概要)
*

  • 詳細的功能描述
  • @property 型別 $prop 屬性描述
  • @author ${AUTHOR}
  • @package application.components(參見路徑別名)

/
3.3.3方法註釋
/
*

  • 功能描述
  • @param 型別 $fields 描述
  • @return 型別 描述
    */

3.3.4屬性註釋
/**

  • @var 型別 KaTeX parse error: Unexpected character: '' at position 701: …)代替dataFile()。 ̲ 有時字首名是有用的: …i = 0; $i < count; $i++) { … }

3.4.5常量名
量全部使用大寫字母和下滑線組成,常量的名稱中不允許出現小寫字母,可使用分隔符作為下劃線。
3.5書寫規則
3.5.1檔案
1)所有的PHP檔案必須使用Unix LF(換行)作為行結束符。
2)所有PHP檔案必須以一個空行結束。
3)純PHP程式碼的檔案關閉標籤?>必須省略
3.5.2行
1)行長度不可有硬限制。
2)行實際長度不應超過80個字元;較長的行應當被拆分成多個不超過80個字元的後續行。
3)空行可以用來改善可讀性和區分相關的程式碼塊。
4)一行不應多於一個語句。
3.5.3縮排
每個縮排的單位約定是4個空格的縮排,並且不可使用製表符作為縮排,需每個參與專案的開發人員在編輯器(Eclipse、EditPlus、Zend Studio等)中進行強制設定將TAB轉化為4個空格,以防在編寫程式碼時遺忘而造成格式上的不規範。
3.5.4控制結構
對於控制結構的樣式規則概括如下:
1)控制結構關鍵詞之後必須有一個空格
2)左括號之後不可有空格
3)右括號之前不可有空格
4)在右括號和左花括號之間必須有一個空格
5)程式碼主體必須有一次縮排
6)右花括號必須主體的下一行
每個結構的主體必須被括在花括號裡。這結構看上去更標準化,並且當加新行的時候可以減少引入錯誤的可能性。
3.5.4.1if,elseif, else
一個if結構看起來應該像下面這樣。注意括號,空格,花括號的位置;並且else和elseif和前一個主體的右花括號在同一行。
//<?php
if ( e x p r 1 ) / / i f b o d y e l s e i f ( expr1) { // if body } elseif ( expr2) {
// elseif body
} else {
// else body;
}
關鍵詞elseif應該替代else if使用以保持所有的控制關鍵詞像一個單詞。
3.5.4.2switch, case
一個switch結構看起來應該像下面這樣。注意括號,空格和花括號。case語句必須從switch處縮排,並且break關鍵字(或其他中止關鍵字)必須和case主體縮排在同級。如果一個非空的case主體往下落空則必須有一個類似// no break的註釋。

//<?php
switch ($expr) {
case 0:
echo ‘First case, with a break’;
break;
case 1:
echo ‘Second case, which falls through’;
// no break
case 2:
case 3:
case 4:
echo ‘Third case, return instead of break’;
return;
default:
echo ‘Default case’;
break;
}

3.5.4.3while, do while
一個while語句看起來應該像下面這樣。注意括號,空格和花括號的位置。

//<?php
while ($expr) {
// structure body
}

同樣的,一個do while語句看起來應該像下面這樣。注意括號,空格和花括號的位置。

//<?php
do {
// structure body;
} while ($expr);

3.5.4.4for
一個for語句看起來應該像下面這樣。注意括號,空格和花括號的位置。
//<?php
for ($i = 0; $i < 10; i + + ) / / f o r b o d y 3.5.4.5 f o r e a c h f o r e a c h / / &lt; ? p h p f o r e a c h ( i++) { // for body } 3.5.4.5foreach 一個foreach語句看起來應該像下面這樣。注意括號,空格和花括號的位置。 //&lt;?php foreach ( iterable as $key => $value) {
// foreach body
}
3.5.4.6try, catch
一個try catch語句看起來應該像下面這樣。注意括號,空格和花括號的位置。
//<?php
try {
// try body
} catch (FirstExceptionType $e) {
// catch body
} catch (OtherExceptionType $e) {
// catch body
}

3.5.5運算子
1)每個運算子與兩邊參與運算的值或表示式中間要有一個空格
3.5.6引號
在絕大多數可以使用單引號的場合,禁止使用雙引號(效能考慮)。可以或必須使用單引號的情況包括但不限於下述:
1)字串為固定值,不包含“\t”等特殊轉義字元;
2)陣列的固定下標,例如 a r r a y [ k e y ] ; 3 ) array[&#x27;key&#x27;]; 3)表示式中不需要帶入變數,例如 string = ‘test’;,而非 s t r i n g = &quot; t e s t string = &quot;test var";
3.5.7關鍵詞
1)PHP keywords 必須使用小寫。
2)PHP常量true, false和null必須使用小寫。
3.5.8函式
3.5.9類
1)類必須單獨一個原始檔,並且類名和檔名相同。
2)類的左花括號必須放到下一行,右花括號必須放在類主體的下一行。
3)類檔案“?>”結束標記去掉

//<?php
class Foo
{
[body]
}

4)一個類的extends和implements關鍵詞必須和類名在同一行。

class ClassName extends ParentClass implements ArrayAccess, Countable
{
// constants, properties, methods
}

5)implements一個列表可以被拆分為多個有一次縮排的後續行。如果這麼做,列表的第一項必須要放在下一行,並且每行必須只有一個介面。

class ClassName extends ParentClass implements
ArrayAccess,
Countable,
Serializable
{
// constants, properties, methods
}
3.5.10屬性
1)所有的屬性必須宣告可見性。
2)var關鍵詞不可用來宣告屬性。
3)一個語句不可宣告多個屬性。
4)屬性名稱可以使用單個下劃線作為字首來表明保護或私有的可見性。

class ClassName
{
public $foo = null;
private $_bar = 1;
}
3.5.11方法
1)所有的方法必須宣告可見性。
2)方法名不應只使用單個下劃線來表明是保護或私有的可見性。
3)方法名在宣告之後不可跟隨一個空格。左花括號必須放在下面自成一行,並且右花括號必須放在方法主體的下面自成一行。左括號後面不可有空格,右括號前面不可有空格。
4)一個方法定義看來應該像下面這樣。 注意括號,逗號,空格和花括號:
5)在引數列表中,逗號之前不可有空格,逗號之後必須要有一個空格。
6)方法中有預設值的引數必須放在引數列表的最後面。

class ClassName
{
public function fooBarBaz(KaTeX parse error: Expected 'EOF', got '&' at position 7: arg1, &̲arg2, $arg3 = [])
{
// method body
}
}

7)引數列表可以被分為多個有一次縮排的多個後續行。如果這麼做,列表的第一項必須放在下一行,並且每行必須只放一個引數。
8)當引數列表被分為多行,右括號和左花括號必須夾帶一個空格放在一起自成一行。

class ClassName
{
public function aVeryLongMethodName(
ClassTypeHint KaTeX parse error: Expected 'EOF', got '&' at position 15: arg1, &̲arg2,
array $arg3 = []
) {
// method body
}
}

9)如果存在,abstract和final宣告必須放在可見性宣告前面。
10)如果存在,static宣告必須跟著可見性宣告。
4資料庫命名規範
4.1命名規範
資料庫的所有表(Table)、檢視(View)、索引(Index)、觸發器(Trigger)、函式(Function)和儲存過程(Store Procedure)均應遵循以下命名規範。
1)命名統一用大寫
2)命名只能由小寫字母和數字構成,並且只能是以小寫字母打頭
3)命名應採用能夠準確反映其中文含義的英文單詞或英文單詞縮寫構成,避免出現英文單詞和漢語拼音混用的局面
4)命名長度不可以超過25個字元(表名儘量保持在20個字元的長度,然後再其上建立索引、主鍵、觸發器等等的時候,便於加擴充套件資訊)
5)名稱的各部分之間以"_"(下劃線)連線
6)欄位如有相同定義,應該用相同命名
7)命名應避免用關鍵字,參見附錄一《關鍵字列表》
4.2實體命名
實體(包括庫表、檢視、函式和索引等)命名結構如下:
prefix[_module]_body[_suffix]
1)為字首名,表示資料庫物件的型別
2)為模組名,按應用模組進行分類,為可選項
3)為主體名,應該能夠清楚地說明物件的含義
4)是字尾名,提供特效的含義,比如在該物件需分表存放時使用,如按月分開存放的表,為可選項。
4.2.1字首命名
字首 資料庫物件
t 表(Table)
v 檢視(View)
tri 觸發器(Trigger)
p 儲存過程(Procedure)
tt 臨時表(Temporary Table)
idx 索引(Index)
uk 唯一索引(Unique Index)
pk 主鍵(Primary Key)
fk 外來鍵(Foreign Key)
f 函式(Function)
4.2.2字尾命名
字尾 定義
_HIS 歷史表
_LOG 流水錶
_MAP 對照表
_REL 關係表
_YYYYMMDD 因資料量龐大,需按日分開存放的表
_YYYYMM 因資料量龐大,需按月分開存放的表
4.3欄位命名
欄位命名結構如下:
prefix_body[_suffix]
1)為字首名,為必填項,必須為“f”。
2)為主體名,應該能夠清楚地說明物件的含義
3)是字尾名,提供特效的含義,為可選項。

4.3.1字尾命名
以下是一些特別的字尾,代表了這個欄位特效的含義。在其他的情況,應避免使用以下的字尾。
字尾 定義
_DESC 引數表內的描敘欄位
一般來講是VARCHAR(255)
_FLAG 只可能是True或False的欄位
一般來講是TINYINT(1)
_ID 標識欄位,一般來講是INT(11)
_TYPE 型別欄位,一般來講是CHAR(1)
4.4欄位型別
一般來說, 在保證正確性的前提下,儘量使用最小的資料型別來儲存和表示資料。 小的資料型別一般比大的更快,因為小的資料型別佔用的磁碟空間, 記憶體和cup快取都相對小,需要的cpu處理也要相對少; 這個原則很重要, 但是設計的時候也不要低估需要儲存的資料的資料範圍。
簡單的資料型別需要的cup處理週期更少,比如:對整數的處理比字串處理更容易, 因為字符集和排序規則使得字串比較複雜化了, 兩個典型例子是: 使用mysql的內嵌資料型別來儲存日期和時間而不是字串,使用整數儲存Ip地址而不是字串。
4.4.1數值型別
1)非萬不得已不要使用DOUBLE,不僅僅只是儲存長度的問題,同時還會存在精確性的問題。
2)固定精度的小數,也不建議使用DECIMAL,建議乘以固定倍數轉換成整數儲存,可以大大節省儲存空間,且不會帶來任何附加維護成本。
3)對於整數的儲存,在資料量較大的情況下,建議區分開 TINYINT / INT / BIGINT 的選擇,因為三者所佔用的儲存空間也有很大的差別,能確定不會使用負數的欄位,建議新增unsigned定義。
4.4.2字元型別
1)非萬不得已不要使用 TEXT 資料型別,其處理方式決定了他的效能要低於char或者是varchar型別的處理。
2)定長欄位,建議使用 CHAR 型別,不定長欄位儘量使用 VARCHAR,且僅僅設定適當的最大長度,而不是非常隨意的給一個很大的最大長度限定,因為不同的長度範圍,MySQL也會有不一樣的儲存處理。
4.4.3時間型別
1)儘量使用TIMESTAMP型別,因為其儲存空間只需要 DATETIME 型別的一半。
2)對於只需要精確到某一天的資料型別,建議使用DATE型別,因為他的儲存空間只需要3個位元組,比TIMESTAMP還少。
3)不建議通過INT型別類儲存一個unix timestamp 的值,因為這太不直觀,會給維護帶來不必要的麻煩,同時還不會帶來任何好處。
4.4.4ENUM&SET
1)對於狀態欄位,可以嘗試使用 ENUM 來存放,因為可以極大的降低儲存空間。
2)如果是存放可預先定義的屬性資料,可以嘗試使用SET型別,即使存在多種屬性,同樣可以遊刃有餘,同時還可以節省不小的儲存空間。
4.4.5LOB 型別
強烈反對在資料庫中存放 LOB 型別資料
4.5表結構設計
4.5.1適度冗餘
不需要一定遵守正規化理論,適度的冗餘,讓Query儘量減少Join
4.5.2儘量使用NOT NULL
儘可能把欄位定義成NOT NULL,許多表包含一些欄位允許空的欄位,即使應用需求不需要儲存NULL的資料,因為允許欄位為NULL是預設的。
允許NULL的欄位會佔用掉更多的儲存空間和花掉更多的cpu處理,當為一個可為空的欄位建立索引時, 需要為每項分配一個額外的位元組。即使遇到不需要儲存值到某個欄位,也應當考慮不使用NULL,而是考慮使用0,一個特殊值或者空串來代替。
4.5.3索引
1)唯一確定一條記錄的一個欄位或多個欄位要建立主鍵或者唯一索引,不能唯一確定一條記錄,為了提高查詢效率建普通索引
2)對於取值不能重複,經常作為查詢條件的欄位,應該建唯一索引(主鍵預設唯一索引),並且將查詢條件中該欄位的條件置於第一個位置。沒有必要再建立與該欄位有關的聯合索引。
3)對於經常查詢的欄位,其值不唯一,也應該考慮建立普通索引,查詢語句中該欄位條件置於第一個位置,對聯合索引處理的方法同樣。
4)需要聯合索引(或聯合主鍵)的資料庫要注意索引的順序。SQL語句中的匹配條件也要跟索引的順序保持一致。
5附件
5.1附錄一:MYSQL保留字
ADD ALL ALTER ANALYZE AND AS ASC AUTO_INCREMENT BDB BEFORE BERKELEYDB BETWEEN BIGINT BINARY BLOB BOTH BTREE BY CASCADE CASE CHANGE CHAR CHARACTER CHECK COLLATE COLUMN COLUMNS CONSTRAINT CREATE CROSS CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP DATABASE DATABASES DAY_HOUR DAY_MINUTE DAY_SECOND DEC DECIMAL DEFAULT DELAYED DELETE DESC DESCRIBE DISTINCT DISTINCTROW DIV DOUBLE DROP ELSE
ENCLOSED ERRORS ESCAPED EXISTS EXPLAIN FALSE FIELDS FLOAT FOR
FORCE FOREIGN FROM FULLTEXT FUNCTION GRANT GROUP HASH HAVING
HIGH_PRIORITY HOUR_MINUTE HOUR_SECOND IF IGNORE IN INDEX INFILE INNER
INNODB INSERT INT INTEGER INTERVAL INTO IS JOIN KEY KEYS KILL LEADING
LEFT LIKE LIMIT LINES LOAD LOCALTIME LOCALTIMESTAMP LOCK LONG
LONGBLOB LONGTEXT LOW_PRIORITY MASTER_SERVER_ID MATCH MEDIUMBLOB
MEDIUMINT MEDIUMTEXT MIDDLEINT MINUTE_SECOND MOD MRG_MYISAM
NATURAL NOT NULL NUMERIC ON OPTIMIZE
OPTION OPTIONALLY OR ORDER OUTER OUTFILE
PRECISION PRIMARY PRIVILEGES PROCEDURE PURGE READ
REAL REFERENCES REGEXP RENAME REPLACE REQUIRE
RESTRICT RETURNS REVOKE RIGHT RLIKE RTREE
SELECT SET SHOW SMALLINT SOME SONAME
SPATIAL SQL_BIG_RESULT SQL_CALC_FOUND_ROWS SQL_SMALL_RESULT SSL STARTING
STRAIGHT_JOIN STRIPED TABLE TABLES TERMINATED THEN
TINYBLOB TINYINT TINYTEXT TO TRAILING TRUE TYPES UNION UNIQUE
UNLOCK UNSIGNED UPDATE USAGE USE USER_RESOURCES
USING VALUES VARBINARY VARCHAR VARCHARACTER VARYING
WARNINGS WHEN WHERE WITH WRITE XOR YEAR_MONTH ZEROFILL