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主要是對namespace和class命名規範進行約束,這個規範主要做用是使得autoloader函數可以根據完整的類名從硬盤中自動加載指定的類文件,其中涉及到的「強制」要求有如下幾點:框架
完整的namespace和class命名必須符合結構:\<Vendor Name>\(<Namespace>\)*<Class Name>.php編輯器
Vendor Name(開發者信息)必須是最頂層的namespace,這樣能夠防止本身類庫與其餘開發者類庫出現命名衝突ide
(<Namespace>\)*後面帶有一個正則表達式中的星號,表明Namespace能夠有0個或者多個函數
每一個Namespace之間的分隔符在autoloader函數中,將會被轉化爲目錄分隔符DIRECTORY_SEPARATOR工具
Class Name即類名稱中容許出現_(下劃線),可是在autoloader函數中,該下劃線也會轉化爲DIRECTORY_SEPARATOR
在autoloader函數中經過namespace和class命名來加載類文件時,類文件的後綴名必須是.php
對其中的英文字母大小寫沒有特殊要求
若是符合了上述要求,那麼autoload代碼就以下:
<?php
function autoload($className)
{
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
require $fileName;
}
\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php
\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
\namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php
原文中的 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" 等關鍵字含義請參與RFC 2119文檔。而且本文中不會對這些關鍵字進行翻譯。
代碼文件中MUST使用<?php ?>和<?= ?>兩個代碼標籤;文件編碼MUST使用UTF-8必須不包含BOM。
單個代碼文件SHOULD要麼用於聲明類,函數或者常量等符號,要麼用於進行一些會產生反作用(Side effects)的計算操做,好比輸出和改變全局的設置。SHOULD NOT(不建議)同時在一個單文件中完成這兩項工做。
命名空間和類名稱MUST符合PSR_0規範
類名稱聲明MUST符合StudlyCaps(大寫駱駝拼寫法)
類中常量MUST使用所有大寫,並使用_(下劃線)做爲分割符
函數名稱聲明MUST符合camelCase(小寫駱駝拼寫法)
針對PHP文件
全部的PHP文件MUST使用Unix的LF做爲行結尾
全部的PHP文件MUST是以單一的空白行結尾
在純PHP文件中MUST省略文件結尾的?>標記
針對文件行
MUST NOT對每一行的長度進行硬限制(Hard Limit)
每個行長度軟限制(Soft Limit)MUST爲120個字符。若是樣式檢查的軟件發現文件不符合該軟限制時MUST給予warn可是MUST NOT給予error
每一行SHOULD NOT 超過80個字符。若是實在是超過80個字符,SHOULD分割爲多行
每個非空白行後面MUST NOT有多餘的尾隨空格
空白行 may(能夠)被添加來提升代碼的可讀性,以及用於分割不相關代碼
每一行MUST NOT超過一條語句
在命名空間聲明行後,MUST有一個空白行
文本縮進
代碼MUST 使用4個空格來進行縮進,MUST NOT使用tabs
PHP關鍵字大小寫
PHP關鍵字包括true, false,null在內,MUST 使用小寫
命名空間和Use聲明
在命名空間聲明行後,MUST有一個空白行
Use語句MUST在命名空間聲明行後面
每一行MUST只能有一個Use聲明
全部的Use語句後面,必須有一個空白行
<?php
namespace Vendor\Package;
use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
// ... additional PHP code ...
類聲明:Extents和implements
類聲明的{}大括號必須在兩個獨立行中
若是類聲明中有extends和implements,那麼它們MUST與類聲明在同一行
若是同時有extends與implements,那麼必須先寫extends,再寫implements
若是implements列表有多個,may把他們分割到多行中,每一行單獨縮進。若是這樣作,那麼第一個implements就MUST在新行,而且每一個implements單獨佔用一行。
<?php
namespace Vendor\Package;
use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
class ClassName extends ParentClass implements
\ArrayAccess,
\Countable,
\Serializable
{
// constants, properties, methods
}
類聲明/函數聲明:abstract,final,static
若是一個類或者函數在聲明時,其中包含abstract,final,static三個關鍵字,那麼與可見性關鍵字(public private protected)之間順序爲:abstarct 和final Must在可見性關鍵字以前;而static MUST在可見性關鍵字以後
類屬性
每個類屬性MUST指定它們的可見性
MUST NOT使用var關鍵字來聲明一個類屬性
每一條語句MUST聲明單個屬性
SHOULD NOT使用_(下劃線)做爲屬性名稱的開頭來表示屬性爲protected或private
方法聲明與方法參數
每個方法MUST顯示指定它們的可見性
SHOULD NOT使用_(下劃線)做爲方法名稱的開頭來表示方法爲protected或private
方法名稱後面MUST NOT帶有空格。而且方法的大括號{}MUST分別在單獨的行
方法的括號()內部的先後MUST NOT有空格,
方法的每個參數後面MUST NOT 有空格,多個參數之間的逗號後面MUST 有空格。
含有默認值的參數MUST 放到參數類別後面
參數列表may被分割爲多行,每行縮進一次;(括號緊跟在行數名後面,)在單獨一行,而且與函數聲明縮進對齊,後面緊跟一個空格和函數的大括號{。每個參數MUST在單獨行。
<?php
namespace Vendor\Package;
class ClassName
{
public function foo($arg1, &$arg2, $arg3 = [])
{
// method body
}
public function aVeryLongMethodName(
ClassTypeHint $arg1,
&$arg2,
array $arg3 = []
) {
// method body
}
}
函數調用
在調用函數時,函數名稱與(之間MUST NOT有空格,(和)與參數之間MUST NOT 有空格。
方法的每個參數後面MUST NOT 有空格,多個參數之間的逗號後面MUST 有空格。
調用參數過長時,May把參數分爲多行,每一行一個參數,而且擁有一個縮進。函數的(緊跟在函數名後,)最後一個參數後面的一行,而且不能有縮進。
<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);
$foo->bar(
$longArgument,
$longerArgument,
$muchLongerArgument
);
控制結構
PHP中包含if/else/elseif,switch/case,while/dowhile,for,foreach,try/catch六種控制結構,它們的編碼規範有一部分共性:
控制關鍵字後面MUST有一個空格
控制結構開括號(後面MUST NOT有空格
控制結構閉括號)前面MUST NOT有空格
控制結構開括號(與大括號}之間MUST有一個空格
控制結構體MUST縮進一次
控制結構閉大括號}必須在控制結構體後單獨的一行
它們之間除了上述共性之外,還有各自的規範。
控制結構:if/elseif/else
具體的if編碼規範見下述實例
<?php
if ($expr1) {
// if body
} elseif ($expr2) {
// elseif body
} else {
// else body;
}
請注意上述的空格,括號開閉的位置。
控制結構:switch/case
具體的switch編碼規範見下述實例,請注意它們的空格,括號開閉的位置。
<?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;
}
每個case MUST相對於switch有一個縮進。
若是一個case沒有break或者return之類中斷語句,那麼必須在它相應位置注視// no break
控制結構:while/dowhile
具體的while編碼規範見下述實例,請注意它們的空格,括號開閉的位置。
<?php
while ($expr) {
// structure body
}
do {
// structure body;
} while ($expr);
控制結構:for
具體的for編碼規範見下述實例,請注意它們的空格,括號開閉的位置。
<?php
for ($i = 0; $i < 10; $i++) {
// for body
}
控制結構:foreach
具體的foreach編碼規範見下述實例,請注意它們的空格,括號開閉的位置。
foreach ($iterable as $key => $value) {
// foreach body
}
控制結構:try/catch
具體的try編碼規範見下述實例,請注意它們的空格,括號開閉的位置。
<?php
try {
// try body
} catch (FirstExceptionType $e) {
// catch body
} catch (OtherExceptionType $e) {
// catch body
}
閉包
function和use關鍵字與括號(之間MUST有一個空格
閉包的大開括號MUST與括號)在空一行,而且之間有一個空格
閉包的大閉括號MUST與閉包實體部分分割開,在單獨一行;而且與閉包語句‘;’之間沒有空格
閉包的function 和use的參數與括號()之間MUST NOT有空格,而且多個參數之間的‘,’前面沒有空格,後面有一個空格
若是閉包的參數有默認值,那麼它MUST放在參數列表的後面
閉包的參數列表能夠分多行,具體的請參考實例
<?php
$closureWithArgs = function ($arg1, $arg2) {
// body
};
$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
// body
};
$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
};
PSR-3是關於系統日誌的接口的開發規範,先不翻譯,後面複習php日誌處理再回來翻譯
連接:https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md