代碼風(fēng)格指南
本手冊是基礎(chǔ)代碼規(guī)范(PSR-1)的繼承和擴(kuò)展。
為了盡可能的提升閱讀其他人代碼時的效率,下面例舉了一系列的通用規(guī)則痰驱,特別是有關(guān)于PHP代碼風(fēng)格的录豺。
各個成員項目間的共性組成了這組代碼規(guī)范。當(dāng)開發(fā)者們在多個項目中合作時盖文,本指南將會成為所有這些項目中共用的一組代碼規(guī)范嘱蛋。 因此,本指南的益處不在于這些規(guī)則本身五续,而在于在所有項目中共用這些規(guī)則洒敏。
RFC 2119中的必須(MUST),不可(MUST NOT)疙驾,建議(SHOULD)凶伙,不建議(SHOULD NOT),可以/可能(MAY)等關(guān)鍵詞將在本節(jié)用來做一些解釋性的描述它碎。
1.概述
代碼必須遵守?PSR-1函荣。
代碼必須使用4個空格來進(jìn)行縮進(jìn),而不是用制表符扳肛。
一行代碼的長度不建議有硬限制傻挂;軟限制必須為120個字符,建議每行代碼80個字符或者更少敞峭。
在命名空間(namespace)的聲明下面必須有一行空行踊谋,并且在導(dǎo)入(use)的聲明下面也必須有一行空行。
類(class)的左花括號必須放到其聲明下面自成一行旋讹,右花括號則必須放到類主體下面自成一行殖蚕。
方法(method)的左花括號必須放到其聲明下面自成一行轿衔,右花括號則必須放到方法主體的下一行。
所有的屬性(property)和方法(method)必須有可見性聲明睦疫;抽象(abstract)和終結(jié)(final)聲明必須在可見性聲明之前害驹;而靜態(tài)(static)聲明必須在可見性聲明之后。
在控制結(jié)構(gòu)關(guān)鍵字的后面必須有一個空格蛤育;而方法(method)和函數(shù)(function)的關(guān)鍵字的后面不可有空格宛官。
控制結(jié)構(gòu)的左花括號必須跟其放在同一行,右花括號必須放在該控制結(jié)構(gòu)代碼主體的下一行瓦糕。
控制結(jié)構(gòu)的左括號之后不可有空格底洗,右括號之前也不可有空格。
1.1示例
這個示例中簡單展示了上文中提到的一些規(guī)則:
<?php
namespace?Vendor\Package;
use?FooInterface;
use?BarClass?as?Bar;
use?OtherVendor\OtherPackage\BazClass;
class?Foo?extends?Bar?implements?FooInterface
{
? public?function?sampleFunction($a,?$b?=?null)
? {
? ? ? ? ? if?($a?===?$b) {
? ? ? ? ? ? ? ? ? bar();
}?elseif?($a?>?$b) {
? ? ? ? ? ? ? ? $foo->bar($arg1);
}?else?{
? ? ? ? ? ? ? ?BazClass::bar($arg2,?$arg3);
? ? ? ? ?}
? }
? final?public?static?function?bar()
? {
? ?//?方法主體
? }
}
2.通則
2.1 基礎(chǔ)代碼規(guī)范
代碼必須遵守?PSR-1?中的所有規(guī)則咕娄。
2.2 源文件
所有的PHP源文件必須使用Unix LF(換行)作為行結(jié)束符亥揖。
所有PHP源文件必須以一個空行結(jié)束。
純PHP代碼源文件的關(guān)閉標(biāo)簽?>必須省略圣勒。
2.3. 行
行長度不可有硬限制费变。
行長度的軟限制必須是120個字符;對于軟限制圣贸,代碼風(fēng)格檢查器必須警告但不可報錯挚歧。
一行代碼的長度不建議超過80個字符;較長的行建議拆分成多個不超過80個字符的子行吁峻。
在非空行后面不可有空格滑负。
空行可以用來增強(qiáng)可讀性和區(qū)分相關(guān)代碼塊。
一行不可多于一個語句锡搜。
2.4. 縮進(jìn)
代碼必須使用4個空格橙困,且不可使用制表符來作為縮進(jìn)。
注意:代碼中只使用空格耕餐,且不和制表符混合使用凡傅,將會對避免代碼差異,補(bǔ)丁肠缔,歷史和注解中的一些問題有幫助夏跷。空格的使用還可以使通過調(diào)整細(xì)微的縮進(jìn)來改進(jìn)行間對齊變得更加的簡單明未。
2.5. 關(guān)鍵字和 True/False/Null
PHP關(guān)鍵字(keywords)必須使用小寫字母槽华。
PHP常量true,false和null必須使用小寫字母。
3.命名空間(Namespace)和導(dǎo)入(Use)聲明
命名空間(namespace)的聲明后面必須有一行空行趟妥。
所有的導(dǎo)入(use)聲明必須放在命名空間(namespace)聲明的下面猫态。
一句聲明中,必須只有一個導(dǎo)入(use)關(guān)鍵字。
在導(dǎo)入(use)聲明代碼塊后面必須有一行空行亲雪。
示例:
<?phpnamespaceVendor\Package;useFooClass;useBarClassasBar;useOtherVendor\OtherPackage\BazClass;//... 其它PHP代碼 ...
4.類(class)勇凭,屬性(property)和方法(method)
術(shù)語“類”指所有的類(class),接口(interface)和特性(trait)义辕。
4.1擴(kuò)展(extend)和實現(xiàn)(implement)
一個類的擴(kuò)展(extend)和實現(xiàn)(implement)關(guān)鍵詞必須和類名(class name)在同一行虾标。
類(class)的左花括號必須放在下面自成一行;右花括號必須放在類(class)主體的后面自成一行灌砖。
<?phpnamespaceVendor\Package;useFooClass;useBarClassasBar;useOtherVendor\OtherPackage\BazClass;classClassNameextendsParentClassimplements\ArrayAccess,\Countable{//常量璧函、屬性、方法}
實現(xiàn)(implement)列表可以被拆分為多個縮進(jìn)了一次的子行基显。如果要拆成多個子行蘸吓,列表的第一項必須要放在下一行,并且每行必須只有一個接口(interface)撩幽。
<?phpnamespaceVendor\Package;useFooClass;useBarClassasBar;useOtherVendor\OtherPackage\BazClass;classClassNameextendsParentClassimplements\ArrayAccess,\Countable,\Serializable{//常量美澳、屬性、方法}
4.2.屬性(property)
所有的屬性(property)都必須聲明其可見性摸航。
變量(var)關(guān)鍵字不可用來聲明一個屬性(property)。
一條語句不可聲明多個屬性(property)舅桩。
屬性名(property name)不推薦用單個下劃線作為前綴來表明其保護(hù)(protected)或私有(private)的可見性酱虎。
一個屬性(property)聲明看起來應(yīng)該像下面這樣。
<?phpnamespaceVendor\Package;classClassName{public$foo=null;}
4.3.方法(method)
所有的方法(method)都必須聲明其可見性擂涛。
方法名(method name)不推薦用單個下劃線作為前綴來表明其保護(hù)(protected)或私有(private)的可見性读串。
方法名(method name)在其聲明后面不可有空格跟隨。其左花括號必須放在下面自成一行撒妈,且右花括號必須放在方法主體的下面自成一行恢暖。左括號后面不可有空格,且右括號前面也不可有空格狰右。
一個方法(method)聲明看來應(yīng)該像下面這樣杰捂。 注意括號,逗號棋蚌,空格和花括號的位置:
<?phpnamespaceVendor\Package;classClassName{publicfunctionfooBarBaz($arg1,&$arg2,$arg3=[]) {//方法主體部分 }}
4.4.方法(method)的參數(shù)
在參數(shù)列表中嫁佳,逗號之前不可有空格,而逗號之后則必須要有一個空格谷暮。
方法(method)中有默認(rèn)值的參數(shù)必須放在參數(shù)列表的最后面蒿往。
<?phpnamespaceVendor\Package;classClassName{publicfunctionfoo($arg1,&$arg2,$arg3=[]) {//方法主體部分 }}
參數(shù)列表可以被拆分為多個縮進(jìn)了一次的子行。如果要拆分成多個子行湿弦,參數(shù)列表的第一項必須放在下一行瓤漏,并且每行必須只有一個參數(shù)。
當(dāng)參數(shù)列表被拆分成多個子行,右括號和左花括號之間必須有一個空格并且自成一行蔬充。
<?phpnamespaceVendor\Package;classClassName{publicfunctionaVeryLongMethodName(ClassTypeHint$arg1,&$arg2,array$arg3=[] ) {//方法主體部分 }}
4.5.抽象(abstract)蝶俱,終結(jié)(final)和靜態(tài)(static)
當(dāng)用到抽象(abstract)和終結(jié)(final)來做類聲明時,它們必須放在可見性聲明的前面娃惯。
而當(dāng)用到靜態(tài)(static)來做類聲明時跷乐,則必須放在可見性聲明的后面。
<?phpnamespaceVendor\Package;abstractclassClassName{protectedstatic$foo;abstractprotectedfunctionzim();finalpublicstaticfunctionbar() {//方法主體部分 }}
4.6. 調(diào)用方法和函數(shù)
調(diào)用一個方法或函數(shù)時趾浅,在方法名或者函數(shù)名和左括號之間不可有空格愕提,左括號之后不可有空格,右括號之前也不可有空格皿哨。參數(shù)列表中浅侨,逗號之前不可有空格,逗號之后則必須有一個空格证膨。
<?phpbar();$foo->bar($arg1);Foo::bar($arg2,$arg3);
參數(shù)列表可以被拆分成多個縮進(jìn)了一次的子行如输。如果拆分成子行,列表中的第一項必須放在下一行央勒,并且每一行必須只能有一個參數(shù)不见。
<?php$foo->bar($longArgument,$longerArgument,$muchLongerArgument);
5.控制結(jié)構(gòu)
下面是對于控制結(jié)構(gòu)代碼風(fēng)格的概括:
控制結(jié)構(gòu)的關(guān)鍵詞之后必須有一個空格。
控制結(jié)構(gòu)的左括號之后不可有空格崔步。
控制結(jié)構(gòu)的右括號之前不可有空格稳吮。
控制結(jié)構(gòu)的右括號和左花括號之間必須有一個空格。
控制結(jié)構(gòu)的代碼主體必須進(jìn)行一次縮進(jìn)井濒。
控制結(jié)構(gòu)的右花括號必須主體的下一行灶似。
每個控制結(jié)構(gòu)的代碼主體必須被括在花括號里。這樣可是使代碼看上去更加標(biāo)準(zhǔn)化瑞你,并且加入新代碼的時候還可以因此而減少引入錯誤的可能性酪惭。
5.1.if,elseif者甲,else
下面是一個if條件控制結(jié)構(gòu)的示例春感,注意其中括號,空格和花括號的位置过牙。同時注意else和elseif要和前一個條件控制結(jié)構(gòu)的右花括號在同一行甥厦。
<?phpif($expr1) {//if body}elseif($expr2) {//elseif body}else{//else body;}
推薦用elseif來替代else if,以保持所有的條件控制關(guān)鍵字看起來像是一個單詞寇钉。
5.2.switch刀疙,case
下面是一個switch條件控制結(jié)構(gòu)的示例,注意其中括號扫倡,空格和花括號的位置谦秧。case語句必須要縮進(jìn)一級竟纳,而break關(guān)鍵字(或其他中止關(guān)鍵字)必須和case結(jié)構(gòu)的代碼主體在同一個縮進(jìn)層級。如果一個有主體代碼的case結(jié)構(gòu)故意的繼續(xù)向下執(zhí)行則必須要有一個類似于// no break的注釋疚鲤。
<?phpswitch($expr) {case0:echo'First case, with a break';break;case1:echo'Second case, which falls through';//no breakcase2:case3:case4:echo'Third case, return instead of break';return;default:echo'Default case';break;}
5.3.while锥累,do while
下面是一個while循環(huán)控制結(jié)構(gòu)的示例,注意其中括號集歇,空格和花括號的位置桶略。
<?phpwhile($expr) {//structure body}
下面是一個do while循環(huán)控制結(jié)構(gòu)的示例,注意其中括號诲宇,空格和花括號的位置际歼。
<?phpdo{//structure body;}while($expr);
5.4.for
下面是一個for循環(huán)控制結(jié)構(gòu)的示例,注意其中括號姑蓝,空格和花括號的位置鹅心。
<?phpfor($i=0;$i<10;$i++) {//for body}
5.5.foreach
下面是一個foreach循環(huán)控制結(jié)構(gòu)的示例,注意其中括號纺荧,空格和花括號的位置旭愧。
<?phpforeach($iterableas$key=>$value) {//foreach body}
5.6.try,catch
下面是一個try catch異常處理控制結(jié)構(gòu)的示例,注意其中括號宙暇,空格和花括號的位置输枯。
<?phptry{//try body}catch(FirstExceptionType$e) {//catch body}catch(OtherExceptionType$e) {//catch body}
6.閉包
聲明閉包時所用的function關(guān)鍵字之后必須要有一個空格,而use關(guān)鍵字的前后都要有一個空格占贫。
閉包的左花括號必須跟其在同一行用押,而右花括號必須在閉包主體的下一行。
閉包的參數(shù)列表和變量列表的左括號后面不可有空格靶剑,右括號的前面也不可有空格。
閉包的參數(shù)列表和變量列表中逗號前面不可有空格池充,而逗號后面則必須有空格桩引。
閉包的參數(shù)列表中帶默認(rèn)值的參數(shù)必須放在參數(shù)列表的結(jié)尾部分。
下面是一個閉包的示例收夸。注意括號坑匠,空格和花括號的位置。
<?php$closureWithArgs=function($arg1,$arg2) {//body};$closureWithArgsAndVars=function($arg1,$arg2)use($var1,$var2) {//body};
參數(shù)列表和變量列表可以被拆分成多個縮進(jìn)了一級的子行卧惜。如果要拆分成多個子行厘灼,列表中的第一項必須放在下一行,并且每一行必須只放一個參數(shù)或變量咽瓷。
當(dāng)列表(不管是參數(shù)還是變量)最終被拆分成多個子行设凹,右括號和左花括號之間必須要有一個空格并且自成一行。
下面是一個參數(shù)列表和變量列表被拆分成多個子行的示例茅姜。
<?php$longArgs_noVars=function($longArgument,$longerArgument,$muchLongerArgument) {//body};$noArgs_longVars=function()use($longVar1,$longerVar2, $muchLongerVar3) {//body};$longArgs_longVars=function($longArgument,$longerArgument,$muchLongerArgument)use($longVar1,$longerVar2, $muchLongerVar3) {//body};$longArgs_shortVars=function($longArgument,$longerArgument,$muchLongerArgument)use($var1) {//body};$shortArgs_longVars=function($arg)use($longVar1,$longerVar2, $muchLongerVar3) {//body};
把閉包作為一個參數(shù)在函數(shù)或者方法中調(diào)用時闪朱,依然要遵守上述規(guī)則。
<?php$foo->bar($arg1,function($arg2)use($var1) {//body },$arg3);
7.結(jié)論
本指南有意的省略了許多元素的代碼風(fēng)格。主要包括:
全局變量和全局常量的聲明
函數(shù)聲明
操作符和賦值
行間對齊
注釋和文檔塊
類名的前綴和后綴
最佳實踐
以后的代碼規(guī)范中可能會修正或擴(kuò)展本指南中規(guī)定的代碼風(fēng)格奋姿。