我也學php:編碼規範/翻譯自PSR

PHP社區百花齊放,擁有大量的函數庫、框架和組件。PHP開發者一般會在本身的項目中使用若干個外部庫,於是PHP代碼遵循或儘可能接近同一個代碼風格就很是重要,可讓開發者方便地把多個代碼庫集成在本身的項目中。php

框架互操做組(即PHP標準組)發佈了一系列代碼風格推薦標準,即PSR-0,PSR-1,PSR-2和PSR-3。 不要讓這些名稱所混淆,這些推薦僅是一些被其它項目所遵循的規則,如Drupal, Zend, Symfony, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium等,你能夠把這些規則用在本身的項目中,或者繼續使用你本身的風格。git

一般狀況下,你的PHP代碼應該遵循其中一項或多項標準,從而其餘開發者能夠方便地閱讀和使用你的代碼。這些標準都是在前一個標準 上附加新的規則,因此使用PSR-1就同時要求遵循PSR-0,但能夠不遵循PSR-2。github

可使用PHP_CodeSniffer來檢查代碼是否符合這些標準,文本編輯器插件Sublime Text 2還能提供實時檢查。若是不符合規範,可使用Fabien Potencier提供的工具PHP Coding Standards Fixer自動修復,不用本身手工修復。正則表達式

 PSR完整地址爲:https://github.com/php-fig/fig-standards閉包


PSR-0:類命名與autoloader之間的規範

PSR-0主要是對namespace和class命名規範進行約束,這個規範主要做用是使得autoloader函數可以根據完整的類名從硬盤中自動加載指定的類文件,其中涉及到的「強制」要求有如下幾點:框架

  1. 完整的namespace和class命名必須符合結構:\<Vendor Name>\(<Namespace>\)*<Class Name>.php編輯器

  2. Vendor Name(開發者信息)必須是最頂層的namespace,這樣能夠防止本身類庫與其餘開發者類庫出現命名衝突ide

  3. (<Namespace>\)*後面帶有一個正則表達式中的星號,表明Namespace能夠有0個或者多個函數

  4. 每一個Namespace之間的分隔符在autoloader函數中,將會被轉化爲目錄分隔符DIRECTORY_SEPARATOR工具

  5. Class Name即類名稱中容許出現_(下劃線),可是在autoloader函數中,該下劃線也會轉化爲DIRECTORY_SEPARATOR

  6. 在autoloader函數中經過namespace和class命名來加載類文件時,類文件的後綴名必須是.php

  7. 對其中的英文字母大小寫沒有特殊要求

若是符合了上述要求,那麼autoload代碼就以下:

  1. <?php  

  2.   

  3. function autoload($className)  

  4. {  

  5.     $className = ltrim($className'\\');  

  6.     $fileName  = '';  

  7.     $namespace = '';  

  8.     if ($lastNsPos = strrpos($className'\\')) {  

  9.         $namespace = substr($className, 0, $lastNsPos);  

  10.         $className = substr($className$lastNsPos + 1);  

  11.         $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;  

  12.     }  

  13.     $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';  

  14.   

  15.     require $fileName;  

  16. }  


  1. \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php  

  2. \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php  

  3. \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php  

  4. \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php  

  5. \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php  

  6. \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php  


PSR-1:簡單編碼規範

原文中的 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" 等關鍵字含義請參與RFC 2119文檔。而且本文中不會對這些關鍵字進行翻譯。

  1. 代碼文件中MUST使用<?php ?>和<?= ?>兩個代碼標籤;文件編碼MUST使用UTF-8必須不包含BOM。

  2. 單個代碼文件SHOULD要麼用於聲明類,函數或者常量等符號,要麼用於進行一些會產生反作用(Side effects)的計算操做,好比輸出和改變全局的設置。SHOULD NOT(不建議)同時在一個單文件中完成這兩項工做。

  3. 命名空間和類名稱MUST符合PSR_0規範

  4. 類名稱聲明MUST符合StudlyCaps(大寫駱駝拼寫法)

  5. 類中常量MUST使用所有大寫,並使用_(下劃線)做爲分割符

  6. 函數名稱聲明MUST符合camelCase(小寫駱駝拼寫法)

PSR-2:編碼風格

針對PHP文件

  1. 全部的PHP文件MUST使用Unix的LF做爲行結尾

  2. 全部的PHP文件MUST是以單一的空白行結尾

  3. 在純PHP文件中MUST省略文件結尾的?>標記

針對文件行

  1. MUST NOT對每一行的長度進行硬限制(Hard Limit)

  2. 每個行長度軟限制(Soft Limit)MUST爲120個字符。若是樣式檢查的軟件發現文件不符合該軟限制時MUST給予warn可是MUST NOT給予error

  3. 每一行SHOULD NOT 超過80個字符。若是實在是超過80個字符,SHOULD分割爲多行

  4. 每個非空白行後面MUST NOT有多餘的尾隨空格

  5. 空白行 may(能夠)被添加來提升代碼的可讀性,以及用於分割不相關代碼

  6. 每一行MUST NOT超過一條語句

  7. 在命名空間聲明行後,MUST有一個空白行

文本縮進

  1. 代碼MUST 使用4個空格來進行縮進,MUST NOT使用tabs

PHP關鍵字大小寫

  1. PHP關鍵字包括true, false,null在內,MUST 使用小寫

命名空間和Use聲明

  1. 在命名空間聲明行後,MUST有一個空白行

  2. Use語句MUST在命名空間聲明行後面

  3. 每一行MUST只能有一個Use聲明

  4. 全部的Use語句後面,必須有一個空白行

  1. <?php  

  2. namespace Vendor\Package;  

  3.   

  4. use FooClass;  

  5. use BarClass as Bar;  

  6. use OtherVendor\OtherPackage\BazClass;  

  7.   

  8. // ... additional PHP code ...  

類聲明:Extents和implements

  1. 類聲明的{}大括號必須在兩個獨立行中

  2. 若是類聲明中有extends和implements,那麼它們MUST與類聲明在同一行

  3. 若是同時有extends與implements,那麼必須先寫extends,再寫implements

  4. 若是implements列表有多個,may把他們分割到多行中,每一行單獨縮進。若是這樣作,那麼第一個implements就MUST在新行,而且每一個implements單獨佔用一行。

  1. <?php  

  2. namespace Vendor\Package;  

  3.   

  4. use FooClass;  

  5. use BarClass as Bar;  

  6. use OtherVendor\OtherPackage\BazClass;  

  7.   

  8. class ClassName extends ParentClass implements  

  9.     \ArrayAccess,  

  10.     \Countable,  

  11.     \Serializable  

  12. {  

  13.     // constants, properties, methods  

  14. }  


類聲明/函數聲明:abstract,final,static

  1. 若是一個類或者函數在聲明時,其中包含abstract,final,static三個關鍵字,那麼與可見性關鍵字(public private protected)之間順序爲:abstarct 和final Must在可見性關鍵字以前;而static MUST在可見性關鍵字以後


類屬性

  1. 每個類屬性MUST指定它們的可見性

  2. MUST NOT使用var關鍵字來聲明一個類屬性

  3. 每一條語句MUST聲明單個屬性

  4. SHOULD NOT使用_(下劃線)做爲屬性名稱的開頭來表示屬性爲protected或private

方法聲明與方法參數

  1. 每個方法MUST顯示指定它們的可見性

  2. SHOULD NOT使用_(下劃線)做爲方法名稱的開頭來表示方法爲protected或private

  3. 方法名稱後面MUST NOT帶有空格。而且方法的大括號{}MUST分別在單獨的行

  4. 方法的括號()內部的先後MUST NOT有空格,

  5. 方法的每個參數後面MUST NOT 有空格,多個參數之間的逗號後面MUST 有空格。

  6. 含有默認值的參數MUST 放到參數類別後面

  7. 參數列表may被分割爲多行,每行縮進一次;(括號緊跟在行數名後面,)在單獨一行,而且與函數聲明縮進對齊,後面緊跟一個空格和函數的大括號{。每個參數MUST在單獨行。

  1. <?php  

  2. namespace Vendor\Package;  

  3.   

  4. class ClassName  

  5. {  

  6.     public function foo($arg1, &$arg2$arg3 = [])  

  7.     {  

  8.         // method body  

  9.     }  

  10.      public function aVeryLongMethodName(  

  11.         ClassTypeHint $arg1,  

  12.         &$arg2,  

  13.         array $arg3 = []  

  14.     ) {  

  15.         // method body  

  16.     }  

  17. }  

函數調用

  1. 在調用函數時,函數名稱與(之間MUST NOT有空格,(和)與參數之間MUST NOT 有空格。

  2. 方法的每個參數後面MUST NOT 有空格,多個參數之間的逗號後面MUST 有空格。

  3. 調用參數過長時,May把參數分爲多行,每一行一個參數,而且擁有一個縮進。函數的(緊跟在函數名後,)最後一個參數後面的一行,而且不能有縮進。

  1. <?php  

  2. bar();  

  3. $foo->bar($arg1);  

  4. Foo::bar($arg2$arg3);  

  5.   

  6. $foo->bar(  

  7.     $longArgument,  

  8.     $longerArgument,  

  9.     $muchLongerArgument  

  10. );  


控制結構

PHP中包含if/else/elseif,switch/case,while/dowhile,for,foreach,try/catch六種控制結構,它們的編碼規範有一部分共性:

  1. 控制關鍵字後面MUST有一個空格

  2. 控制結構開括號(後面MUST NOT有空格

  3. 控制結構閉括號)前面MUST NOT有空格

  4. 控制結構開括號(與大括號}之間MUST有一個空格

  5. 控制結構體MUST縮進一次

  6. 控制結構閉大括號}必須在控制結構體後單獨的一行

它們之間除了上述共性之外,還有各自的規範。

控制結構:if/elseif/else

具體的if編碼規範見下述實例

  1. <?php  

  2. if ($expr1) {  

  3.     // if body  

  4. elseif ($expr2) {  

  5.     // elseif body  

  6. else {  

  7.     // else body;  

  8. }  

請注意上述的空格,括號開閉的位置。

控制結構:switch/case

具體的switch編碼規範見下述實例,請注意它們的空格,括號開閉的位置。

  1. <?php  

  2. switch ($expr) {  

  3.     case 0:  

  4.         echo 'First case, with a break';  

  5.         break;  

  6.     case 1:  

  7.         echo 'Second case, which falls through';  

  8.         // no break  

  9.     case 2:  

  10.     case 3:  

  11.     case 4:  

  12.         echo 'Third case, return instead of break';  

  13.         return;  

  14.     default:  

  15.         echo 'Default case';  

  16.         break;  

  17. }  

  1. 每個case MUST相對於switch有一個縮進。

  2. 若是一個case沒有break或者return之類中斷語句,那麼必須在它相應位置注視// no break

控制結構:while/dowhile

具體的while編碼規範見下述實例,請注意它們的空格,括號開閉的位置。

  1. <?php  

  2. while ($expr) {  

  3.     // structure body  

  4. }  

  5. do {  

  6.     // structure body;  

  7. while ($expr);  


控制結構:for

具體的for編碼規範見下述實例,請注意它們的空格,括號開閉的位置。

  1. <?php  

  2. for ($i = 0; $i < 10; $i++) {  

  3.     // for body  

  4. }  


控制結構:foreach

具體的foreach編碼規範見下述實例,請注意它們的空格,括號開閉的位置。

  1. foreach ($iterable as $key => $value) {  

  2.     // foreach body  

  3. }  


控制結構:try/catch

具體的try編碼規範見下述實例,請注意它們的空格,括號開閉的位置。

  1. <?php  

  2. try {  

  3.     // try body  

  4. } catch (FirstExceptionType $e) {  

  5.     // catch body  

  6. } catch (OtherExceptionType $e) {  

  7.     // catch body  

  8. }  

閉包

  1. function和use關鍵字與括號(之間MUST有一個空格

  2. 閉包的大開括號MUST與括號)在空一行,而且之間有一個空格

  3. 閉包的大閉括號MUST與閉包實體部分分割開,在單獨一行;而且與閉包語句‘;’之間沒有空格

  4. 閉包的function 和use的參數與括號()之間MUST NOT有空格,而且多個參數之間的‘,’前面沒有空格,後面有一個空格

  5. 若是閉包的參數有默認值,那麼它MUST放在參數列表的後面

  6. 閉包的參數列表能夠分多行,具體的請參考實例

  1. <?php  

  2. $closureWithArgs = function ($arg1$arg2) {  

  3.     // body  

  4. };  

  5.   

  6. $closureWithArgsAndVars = function ($arg1$arg2use ($var1$var2) {  

  7.     // body  

  8. };  

  9. $longArgs_noVars = function (  

  10.     $longArgument,  

  11.     $longerArgument,  

  12.     $muchLongerArgument  

  13. ) {  

  14.    // body  

  15. };  

  16.   

  17. $noArgs_longVars = function () use (  

  18.     $longVar1,  

  19.     $longerVar2,  

  20.     $muchLongerVar3  

  21. ) {  

  22.    // body  

  23. };  

  24.   

  25. $longArgs_longVars = function (  

  26.     $longArgument,  

  27.     $longerArgument,  

  28.     $muchLongerArgument  

  29. use (  

  30.     $longVar1,  

  31.     $longerVar2,  

  32.     $muchLongerVar3  

  33. ) {  

  34.    // body  

  35. };  

  36.   

  37. $longArgs_shortVars = function (  

  38.     $longArgument,  

  39.     $longerArgument,  

  40.     $muchLongerArgument  

  41. use ($var1) {  

  42.    // body  

  43. };  

  44.   

  45. $shortArgs_longVars = function ($arguse (  

  46.     $longVar1,  

  47.     $longerVar2,  

  48.     $muchLongerVar3  

  49. ) {  

  50.    // body  

  51. };  

PSR-3:日誌接口

PSR-3是關於系統日誌的接口的開發規範,先不翻譯,後面複習php日誌處理再回來翻譯

連接:https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md

相關文章
相關標籤/搜索