我不知道有沒有人發(fā)轉(zhuǎn)貼過PHP編碼規(guī)范,但為了大家以后的交流,統(tǒng)一代碼格式,我想實(shí)用的,你看呢?
發(fā)表時(shí)間:2023-07-17 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]PHP編碼規(guī)范1. 介紹 1.1. 標(biāo)準(zhǔn)化的重要** 標(biāo)準(zhǔn)化問題在某些方面上讓每個(gè)人頭痛,讓人人都覺得大家處于同樣的境地。這有助于讓這些建議在許多的項(xiàng)目中不斷演進(jìn),許多公司花費(fèi)了許多星期逐子字逐句的...
PHP編碼規(guī)范
1. 介紹
1.1. 標(biāo)準(zhǔn)化的重要**
標(biāo)準(zhǔn)化問題在某些方面上讓每個(gè)人頭痛,讓人人都覺得大家處于同樣的境地。這有助于讓這些建議在許多的項(xiàng)目中不斷演進(jìn),許多公司花費(fèi)了許多星期逐子字逐句的進(jìn)行爭(zhēng)論。標(biāo)準(zhǔn)化不是特殊的個(gè)人風(fēng)格,它對(duì)本地改良是完全開放的。
1.2. 優(yōu)點(diǎn)
當(dāng)一個(gè)項(xiàng)目嘗試著遵守公用的標(biāo)準(zhǔn)時(shí),會(huì)有以下好處:
· 程序員可以了解任何代碼,弄清程序的狀況
· 新人可以很快的適應(yīng)環(huán)境
· 防止新接觸php的人出于節(jié)省時(shí)間的需要,自創(chuàng)一套風(fēng)格并養(yǎng)成終生的習(xí)慣
· 防止新接觸php的人一次次的犯同樣的錯(cuò)誤
· 在一致的環(huán)境下,人們可以減少犯錯(cuò)的機(jī)會(huì)
· 程序員們有了一致的敵人
1.3. 缺點(diǎn)
· 因?yàn)闃?biāo)準(zhǔn)由一些不懂得php的人所制定,所以標(biāo)準(zhǔn)通?瓷先ズ苌
· 因?yàn)闃?biāo)準(zhǔn)跟我做的不一樣,所以標(biāo)準(zhǔn)通?瓷先ズ苌
· 標(biāo)準(zhǔn)降低了創(chuàng)造力
· 標(biāo)準(zhǔn)在長(zhǎng)期互相合作的人群中是沒有必要的
· 標(biāo)準(zhǔn)強(qiáng)迫太多的格式
1.4. 討論
許多項(xiàng)目的經(jīng)驗(yàn)?zāi)艿贸鲞@樣的結(jié)論:采用編程標(biāo)準(zhǔn)可以使項(xiàng)目更加順利地完成。標(biāo)準(zhǔn)是成功的關(guān)鍵么?當(dāng)然不。但它們可以幫助我們,而且我們需要我們能得到的所有的幫助!老實(shí)說,對(duì)一個(gè)細(xì)節(jié)標(biāo)準(zhǔn)的大部分爭(zhēng)論主要是源自自負(fù)思想。對(duì)一個(gè)合理的標(biāo)準(zhǔn)的很少?zèng)Q定能被說為是缺乏技術(shù)**的話,那只是口味的原因罷了。所以,要靈活的控制自負(fù)思想,記住,任何項(xiàng)目都取決于團(tuán)隊(duì)合作的努力。
1.5. 解釋
1.5.1. 標(biāo)準(zhǔn)實(shí)施
首先應(yīng)該在開發(fā)小組的內(nèi)部找出所有的最重要的元素,也許標(biāo)準(zhǔn)對(duì)你的狀況還不夠恰當(dāng)。它可能已經(jīng)概括了 重要的問題,也可能還有人對(duì)其中的某些問題表示強(qiáng)烈的反對(duì)。無論在什么情況下,只要最后順利的話,人們將成熟的明白到這個(gè)標(biāo)準(zhǔn)是合理的,然后其他的程序員們也會(huì)發(fā)現(xiàn)它的合理**,并覺得帶著一些保留去遵循這一標(biāo)準(zhǔn)是值得的。如果沒有自愿的合作,可以制定需求:標(biāo)準(zhǔn)一定要經(jīng)過代碼的檢驗(yàn)。如果沒有檢驗(yàn)的話,這個(gè)解決方案僅僅是一個(gè)建立在不精確的基礎(chǔ)上的一大群可笑的人。
1.5.2. 認(rèn)同觀點(diǎn)
1. 這行不通;
2. 也許可行吧,但是它既不實(shí)用又無聊;
3. 這是真的,而且我也告訴過你;
4. 這個(gè)是我先想到的;
5. 本來就應(yīng)該這樣。
如果您帶著否定的成見而來看待事物的話,請(qǐng)您保持開放的思想。你仍可以做出它是廢話的結(jié)論,但是做出結(jié)論的方法就是你必須要能夠接受不同的思想。請(qǐng)您給自己一點(diǎn)時(shí)間去做到它。
1.5.3. 項(xiàng)目的四個(gè)階段
1. 數(shù)據(jù)庫(kù)結(jié)構(gòu)
2. 設(shè)計(jì)
3. 數(shù)據(jù)層
4. HTML層
2. 命名規(guī)則
2.1. 合適的命名
命名是程序規(guī)劃的核心。古人相信只要知道一個(gè)人真正的名字就會(huì)獲得凌駕于那個(gè)人之上的不可思議的力量。只要你給事物想到正確的名字,就會(huì)給你以及后來的人帶來比代碼更強(qiáng)的力量。別笑!
名字就是事物在它所處的生態(tài)環(huán)境中一個(gè)長(zhǎng)久而深遠(yuǎn)的結(jié)果?偟膩碚f,只有了解系統(tǒng)的程序員才能為系統(tǒng)取出最合適的名字。如果所有的命名都與其自然相適合,則關(guān)系清晰,含義可以推導(dǎo)得出,一般人的推想也能在意料之中。
如果你發(fā)覺你的命名只有少量能和其對(duì)應(yīng)事物相匹配的話, 最好還是重新好好再看看你的設(shè)計(jì)吧。
2.2. 類命名
· 在為類(class )命名前首先要知道它是什么。如果通過類名的提供的線索,你還是想不起這個(gè)類是什么的話,那么你的設(shè)計(jì)就還做的不夠好。
· 超過三個(gè)詞組成的混合名是容易造成系統(tǒng)各個(gè)實(shí)體間的混淆,再看看你的設(shè)計(jì),嘗試使用(CRC Session card)看看該命名所對(duì)應(yīng)的實(shí)體是否有著那么多的功用。
· 對(duì)于派生類的命名應(yīng)該避免帶其父類名的誘惑,一個(gè)類的名字只與它自身有關(guān),和它的父類叫什么無關(guān)。
· 有時(shí)后綴名是有用的,例如:如果你的系統(tǒng)使用了代理(agent ),那么就把某個(gè)部件命名為“下載代理”(DownloadAgent)用以真正的傳送信息。
2.3. 方法和函數(shù)命名
· 通常每個(gè)方法和函數(shù)都是執(zhí)行一個(gè)動(dòng)作的,所以對(duì)它們的命名應(yīng)該清楚的說明它們是做什么的:用CheckForErrors()代替ErrorCheck(),用DumpDataToFile()代替DataFile()。這么做也可以使功能和數(shù)據(jù)成為更可區(qū)分的物體。
· 有時(shí)后綴名是有用的:
o Max - 含義為某實(shí)體所能賦予的最大值。
o Cnt - 一個(gè)運(yùn)行中的計(jì)數(shù)變量的當(dāng)前值。
o Key - 鍵值。
例如:RetryMax 表示最多重試次數(shù),RetryCnt 表示當(dāng)前重試次數(shù)。
· 有時(shí)前綴名是有用的:
o Is - 含義為問一個(gè)關(guān)于某樣事物的問題。無論何時(shí),當(dāng)人們看到Is就會(huì)知道這是一個(gè)問題。
o Get - 含義為取得一個(gè)數(shù)值。
o Set - 含義為設(shè)定一個(gè)數(shù)值
例如:IsHitRetryLimit。
2.4. 縮寫詞不要全部使用大寫字母
· 無論如何,當(dāng)遇到以下情況,你可以用首字母大寫其余字母小寫來代替全部使用大寫字母的方法來表示縮寫詞。
使用: GetHtmlStatistic.
不使用: GetHTMLStatistic.
理由
· 當(dāng)命名含有縮略詞時(shí),人們似乎有著非常不同的直覺。統(tǒng)一規(guī)定是最好,這樣一來,命名的含義就完全可以預(yù)知了。
舉個(gè)NetworkABCKey的例子,注意C是應(yīng)該是ABC里面的C還是key里面的C,這個(gè)是很令人費(fèi)解的。有些人不在意這些,其他人卻很討厭這樣。所以你會(huì)在不同的代碼里看到不同的規(guī)則,使得你不知道怎么去叫它。
例如
class FluidOz // 不要寫成 FluidOZ
class GetHtmlStatistic // 不要寫成 GetHTMLStatistic
2.5. 類命名
· 使用大寫字母作為詞的分隔,其他的字母均使用小寫
· 名字的首字母使用大寫
· 不要使用下劃線('_')
理由
· 根據(jù)很多的命名方式,大部分人認(rèn)為這樣是最好的方式。
例如
class NameOneTwo
class Name
2.6. 類庫(kù)命名
· 目前命名空間正在越來越廣泛的被采用,以避免不同廠商和團(tuán)體類庫(kù)間的類名沖突。
· 當(dāng)尚未采用命名空間的時(shí)候,為了避免類名沖突,一般的做法是在類名前加上獨(dú)特的前綴,兩個(gè)字符就可以了,當(dāng)然多用一些會(huì)更好。
例如
John Johnson的數(shù)據(jù)結(jié)構(gòu)類庫(kù)可以用Jj做為前綴,如下:
class JjLinkList
{
}
另一種折中方式是建立包含類庫(kù)目錄(事實(shí)上Java也是這么做的),以不通的目錄代表不同的命名空間。
例如
Microsoft的數(shù)據(jù)庫(kù)相關(guān)類庫(kù)可以在:
/classes/com/Microsoft/ Database/DbConn.php
Apache的數(shù)據(jù)庫(kù)相關(guān)類庫(kù)可在:
/classes/org/apache/Database/DbConn.php
2.7. 方法命名
· 采用與類命名一致的規(guī)則
理由
· 使用所有不同規(guī)則的大部分人發(fā)現(xiàn)這是最好的折衷辦法。
例如
class NameOneTwo
{
function DoIt() {};
function HandleError() {};
}
2.8. 類屬**命名
· 屬**命名應(yīng)該以字符‘m’為前綴。
· 前綴‘m’后采用于類命名一致的規(guī)則。
· ‘m’總是在名字的開頭起修飾作用,就像以‘r’開頭表示引用一樣。
理由
· 前綴'm'防止類屬**和方法名發(fā)生任何沖突。你的方法名和屬**名經(jīng)常會(huì)很類似,特別是存取元素。
例如
class NameOneTwo
{
function VarAbc() {};
function ErrorNumber() {};
var $mVarAbc;
var $mErrorNumber;
var $mrName;
}
2.9. 方法中參數(shù)命名
· 第一個(gè)字符使用小寫字母。
· 在首字符后的所有字都按照類命名規(guī)則首字符大寫。
理由
· 可以區(qū)分方法中的一般變量。
· 你可以使用與類名相似的名稱而不至于產(chǎn)生重名沖突。
例如
class NameOneTwo
{
function StartYourEngines(
&$rSomeEngine,
&$rAnotherEngine);
}
2.10. 變量命名
· 所有字母都使用小寫
· 使用'_'作為每個(gè)詞的分界。
理由
· 通過這一途徑,代碼中變量的作用域是清晰的。
· 所有的變量在代碼中都看起來不同,容易辨認(rèn)。
例如
function HandleError($errorNumber)
{
$error = OsErr($errorNumber);
$time_of_error = OsErr->GetTimeOfError();
$error_processor = OsErr->GetErrorProcessor();
}
2.11. 引用變量和函數(shù)返回引用
· 引用必須帶‘r’前綴
理由
· 使得類型不同的變量容易辨認(rèn)
· 它可以確定哪個(gè)方法返回可更改對(duì)象,哪個(gè)方法返回不可更改對(duì)象。
例如
class Test
{
var mrStatus;
function DoSomething(&$rStatus) {};
function &rStatus() {};
}
2.12. 全局變量
· 全局變量應(yīng)該帶前綴‘g’。
理由
· 知道一個(gè)變量的作用域是非常重要的。
例如
global $gLog;
global &$grLog;
2.13. 定義命名 / 全局常量
· 全局常量用'_'分隔每個(gè)單詞。
理由
這是命名全局常量的傳統(tǒng)。你要注意不要與其它的定義相沖突。
例如
define("A_GLOBAL_CONSTANT", "Hello world!");
2.14. 靜態(tài)變量
· 靜態(tài)變量應(yīng)該帶前綴‘s’。
理由
· 知道一個(gè)變量的作用域是非常重要的。
例如
function test()
{
static $msStatus = 0;
}
2.15. 函數(shù)命名
· 函數(shù)名字采用C GNU的慣例,所有的字母使用小寫字母,使用'_'分割單詞。
理由
· 這樣可以更易于區(qū)分相關(guān)聯(lián)的類名。
例如
function some_bloody_function()
{
}
2.16. 錯(cuò)誤返回檢測(cè)規(guī)則
· 檢查所有的系統(tǒng)調(diào)用的錯(cuò)誤信息,除非你要忽略錯(cuò)誤。
· 為每條系統(tǒng)錯(cuò)誤消息定義好系統(tǒng)錯(cuò)誤文本以便include。
3. 書寫規(guī)則
3.1. 大括號(hào) {} 規(guī)則
在三種主要的大括號(hào)放置規(guī)則中,有兩種是可以接受的,如下的第一種是最好的:
· 將大括號(hào)放置在關(guān)鍵詞下方的同列處:
if ($condition) while ($condition)
{ {
... ...
} }
· 傳統(tǒng)的UNIX的括號(hào)規(guī)則是,首括號(hào)與關(guān)鍵詞同行,尾括號(hào)與關(guān)鍵字同列:
if ($condition) { while ($condition) {
... ...
} }
理由
· 引起劇烈爭(zhēng)論的非原則的問題可通過折衷的辦法解決,兩種方法任意一種都是可以接受的,然而對(duì)于大多數(shù)人來說更喜歡第一種。原因就是心理研究學(xué)習(xí)范疇的東西了。
對(duì)于更喜歡第一種還有著更多的原因。如果您使用的字符編輯器支持括號(hào)匹配功能的話(例如vi),最重要的就是有一個(gè)好的樣式。為什么?我們說當(dāng)你有一大塊的程序而且想知道這一大塊程序是在哪兒結(jié)束的話。你先移到開始的括號(hào),按下按鈕編輯器就會(huì)找到與之對(duì)應(yīng)的結(jié)束括號(hào),例如:
if ($very_long_condition && $second_very_long_condition)
{
...
}
else if (...)
{
...
}
從一個(gè)程序塊移動(dòng)到另一個(gè)程序塊只需要用光標(biāo)和你的括號(hào)匹配鍵就可以了,不需找匹配的括號(hào)。
3.2. 縮進(jìn)/制表符/空格 規(guī)則
· 使用制表符縮進(jìn)。
· 使用三到四個(gè)空格為每層次縮進(jìn)。
· 不再使用只要一有需要就縮排的方法。對(duì)于最大縮進(jìn)層數(shù),并沒有一個(gè)固定的規(guī)矩,假如縮進(jìn)層數(shù)大于四或者五層的時(shí)候,你可以考慮著將代碼因數(shù)分解(factoring out code)。
理由
· 許多編程者支持制表符。
· 當(dāng)人們使用差異太大的制表符標(biāo)準(zhǔn)的話,會(huì)使閱讀代碼變得很費(fèi)力。
· 如此多的人愿意限定最大的縮進(jìn)層數(shù),它通常從未被看作是一件工作。我們相信程序員們會(huì)明智的選擇嵌套的深度。
例如
function func()
{
if (something bad)
{
if (another thing bad)
{
while (more input)
{
}
}
}
}
3.3. 小括號(hào)、關(guān)鍵詞和函數(shù) 規(guī)則
· 不要把小括號(hào)和關(guān)鍵詞緊貼在一起,要用空格隔開它們。
· 不要把小括號(hào)和函數(shù)名緊貼在一起。
· 除非必要,不要在Return返回語(yǔ)句中使用小括號(hào)。
理由
· 關(guān)鍵字不是函數(shù)。如果小括號(hào)緊貼著函數(shù)名和關(guān)鍵字,二者很容易被看成是一體的。
例如
if (condition)
{
}
while (condition)
{
}
strcmp($s, $s1);
return 1;
3.4. 別在對(duì)象架構(gòu)函數(shù)中做實(shí)際的工作
別在對(duì)象架構(gòu)構(gòu)造函數(shù)中做實(shí)際的工作, 構(gòu)造函數(shù)應(yīng)該包含變量的初始化和(或)不會(huì)發(fā)生失敗的操作。
理由
· 構(gòu)造不能返回錯(cuò)誤 。
例如
class Device
{
function Device() { /* initialize and other stuff */ }
function Open() { return FAIL; }
};
$dev = new Device;
if (FAIL == $dev->Open()) exit(1);
3.5. If Then Else 格式
布局
這由程序員決定。不同的花括號(hào)樣式會(huì)產(chǎn)生些微不同的樣觀。一個(gè)通用方式是:
if (條件1) // 注釋
{
}
else if (條件2) // 注釋
{
}
else // 注釋
{
}
如果你有用到else if 語(yǔ)句的話,通常最好有一個(gè)else塊以用于處理未處理到的其他情況?梢缘脑挿乓粋(gè)記錄信息注釋在else處,即使在else沒有任何的動(dòng)作。
條件格式
總是將恒量放在等號(hào)/不等號(hào)的左邊,例如:
if ( 6 == $errorNum ) ...
一個(gè)原因是假如你在等式中漏了一個(gè)等號(hào),語(yǔ)法檢查器會(huì)為你報(bào)錯(cuò)。第二個(gè)原因是你能立刻找到數(shù)值而不是在你的表達(dá)式的末端找到它。需要一點(diǎn)時(shí)間來習(xí)慣這個(gè)格式,但是它確實(shí)很有用。
3.6. switch 格式
· 當(dāng)一個(gè)case塊處理后,直接轉(zhuǎn)到下一個(gè)case塊處理,在這個(gè)case塊的最后應(yīng)該加上注釋。
· default case總應(yīng)該存在,它應(yīng)該不被到達(dá),然而如果到達(dá)了就會(huì)觸發(fā)一個(gè)錯(cuò)誤。
· 如果你要?jiǎng)?chuàng)立一個(gè)變量,那就把所有的代碼放在塊中。
例如
switch (...)
{
case 1:
...
// FALL THROUGH
case 2:
{
$v = get_week_number();
...
}
break;
default:
}
3.7. continue,break 和 ? 的使用
3.7.1. Continue 和 Break
Continue 和 break 其實(shí)是變相的隱蔽的 goto方法。
Continue 和 break 像 goto 一樣,它們?cè)诖a中是有魔力的,所以要節(jié)儉(盡可能少)的使用它們。使用了這一簡(jiǎn)單的魔法,由于一些未公開的原因,讀者將會(huì)被定向到只有上帝才知道的地方去。
Continue有兩個(gè)主要的問題:
· 它可以繞過測(cè)試條件。
· 它可以繞過等/不等表達(dá)式。
看看下面的例子,考慮一下問題都在哪兒發(fā)生:
while (TRUE)
{
...
// A lot of code
...
if (/* some condition */) {
continue;
}
...
// A lot of code
...
if ( $i++ > STOP_VALUE) break;
}
注意:"A lot of code"是必須的,這是為了讓程序員們不能那么容易的找出錯(cuò)誤。
通過以上的例子,我們可以得出更進(jìn)一步的規(guī)則:continue 和 break 混合使用是引起災(zāi)難的正確方法。
3.7.2. ?:
麻煩在于人們往往試著在 ? 和 : 之間塞滿了許多的代碼。以下的是一些清晰的連接規(guī)則:
· 把條件放在括號(hào)內(nèi)以使它和其他的代碼相分離。
· 如果可能的話,動(dòng)作可以用簡(jiǎn)單的函數(shù)。
· 把所做的動(dòng)作,“?”,“:”放在不同的行,除非他們可以清楚的放在同一行。
例如
(condition) ? funct1() : func2();
or
(condition)
? long statement
: another long statement;
3.8. 聲明塊的定位
· 聲明代碼塊需要對(duì)齊。
理由
· 清晰。
· 變量初始化的類似代碼塊應(yīng)該列表。
· &應(yīng)靠近類型,而不是變量名。
例如
var $mDate
var& $mrDate
var& $mrName
var $mName
$mDate = 0;
$mrDate = NULL;
$mrName = 0;
$mName = NULL;
3.9. 每行一個(gè)語(yǔ)句
除非這些語(yǔ)句有很密切的聯(lián)系,否則每行只寫一個(gè)語(yǔ)句。
3.10. 短方法
方法代碼要限制在一頁(yè)內(nèi)。