名詞:
MUST: 務必
MUST Not: 務必不要
Should: 最好
Should Not: 最好不要
MAY: 也許
#目錄
#PSR-1 Basic Coding Standard使用標準 基本Coding標準
##1. PSR-1 總覽
-
Files 務必(MUST)使用
<?php
或<?
標籤 -
Files 內的PHP code務必(MUST)使用無BOM的UTF-8
-
Files 最好(Should)只用以宣告Symbols(例如物件、方法、常數)或賦值(例如產生輸出、改變ini設定)
但最好不要(Should not)同時做這兩件事/**同時做宣告和賦值的範例*/ <?php // 賦值(Side effect): change ini settings ini_set('error_reporting', E_ALL); // 賦值(Side effect): loads a file include "file.php"; // 賦值(Side effect): generates output echo "<html>\n"; // 宣告Symbols function foo() { // function body } /**只做宣告而不賦值的範例*/ <?php // 宣告Symbols function foo() { // function body } // conditional declaration is *not* a side effect if (! function_exists('bar')) { function bar() { // function body } }
-
Namespaces 和 classes 務必(MUST)按照PSR:[PSR-0, PSR-4]的autoloading規範
// PHP 5.3(含)之後的版本 <?php namespace Vendor\Model; class Foo { } // PHP 5.2.x(含)之前的版本: <?php class Vendor_Model_Foo { }
-
Class名稱務必(MUST)以大寫開始駝峰命名(StudlyCaps)法來命名
// 範例 <?php namespace Vendor\Model; class Foo { }
-
Class常數務必(MUST)以全大寫命名,若以2個以上字命名,則以底線(underscore)分開之
// 範例 <?php namespace Vendor\Model; class Foo { const VERSION = '1.0'; const DATE_APPROVED = '2012-06-01'; }
-
Method名稱(MUST)以小寫開始駝峰命名法(camelCase)
<?php class ClassName { public function fooBarBaz() { // method body } }
#PSR-2 Coding Style Guide 編碼風格指導
##1. PSR-2 總覽
###檔案面(file)
-
Code務必(MUST)使用4個空白(spaces)當縮排,而非tab
N.b.: Using only spaces, and not mixing spaces with tabs, helps to avoid problems with diffs, patches, history, and annotations. The use of spaces also makes it easy to insert fine-grained sub-indentation for inter-line alignment.
-
File只包含PHP Code時,
?>
務必(MUST)刪除理由是
?>
後若有多出空白,會被瀏覽器解析 -
所有PHP files務必(MUST)使用Unix LF做行尾
-
所有PHP files務必(MUST)以一行空白做結尾
-
每行Code的長度務必不要(MUST Not)有寫死(hard limit)的長度限制;
- 軟性限制務必(MUST)在120字元內;
- 每行最好(Should)不多於80個字元;
-
非空白行的行尾務必不要(MUST Not)有結尾空白格
-
空白行也許(MAY)可增加來促進程式碼可讀性和呈現Code的相關區塊
-
每行Code不要有多於一個陳述(statement)
-
PHP的true, false, null務必(MUST)要小寫
-
Nampspace宣告和use宣告區塊的後面務必(MUST)要有一行空白
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; // ... additional PHP code ...
-
extends & implements務必(MUST)和class name宣告在同一行
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable { // constants, properties, methods }
如果有多重interface要implements, 所有interface前都要有一個縮排, 第一個interface要換行。
<?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 }
###Class, Method, Property面
-
所有屬性(Properties)和方法(Methods)都要宣告可視性(Visibility, 含public, protected, private);
<?php namespace Vendor\Package; class ClassName { public $foo = null; }
-
務必不要(MUST Not)使用
var
來宣告property 可視性var $foo; -
每個statement務必不要(MUST Not)宣告多於一個property
-
Property名稱最好不要(Should Not)用一個底線做前綴來表示protected or private可視性
-
Method名稱最好不要(Should Not)用一個底線做前綴來表示protected or private可視性
-
Method名稱後務必不要(MUST Not)有一個空格
-
Class和Method的左大括弧
{
和右大括弧}
務必(MUST)要獨自為一行 -
Method的左括弧
(
後務必不要(MUST Not)有空格;右括弧)
前務必不要(MUST Not)有空格 -
Method參數list中,每個逗號後面務必(MUST)要有一個空格;每個逗號前面務必不要(MUST Not)有一個空格
####6~9點範例
<?php namespace Vendor\Package; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } }
-
Method參數list也許(MAY)可斷行,若要斷行,每個參數(含第一個)務必(MUST)都要斷行並有一個縮排。
每行務必不可(MUST Not)有多於一個參數<?php namespace Vendor\Package; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body } }
-
abstract和final務必(MUST)在可視性之前宣告
-
static務必(MUST)在可視性之後宣告
11~12點範例
<?php namespace Vendor\Package; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } }
###呼叫Method or Function
-
Method or Function和括弧
()
之間務必不可(MUST Not)有空格 -
左括弧
(
後不可有空格;右括弧)
前不可有空格 -
參數list中,逗號前務必不可(MUST Not)有空格;逗號後務必(MUST)有空格
範例
<?php bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3);
-
參數list可以斷行,每個參數(含第一個)都要斷行並有一個縮排
<?php $foo->bar( $longArgument, $longerArgument, $muchLongerArgument );
###控制結構(Control Structures),例如if-else, switch, while
-
控制結構關鍵字(if, switch...)之後務必(MUST)要有一個空白
-
左括弧
(
後務必不要(MUST Not)有一個空白 -
右括弧
)
前務必不要(MUST Not)有一個空白 -
左大括弧
{
和右大括弧}
之間務必(MUST)要有一個空白;左大括弧
{
之前務必(MUST)有一個空白;
左大括弧{
和控制結構關鍵字要同一行; -
{}
內的Code務必(MUST)要有一個縮排 -
右大括弧
}
務必(MUST)要獨自一行 -
if, elseif, else範例
<?php if ($expr1) { // if body } elseif ($expr2) { // elseif body } else { // else body; }
-
switch, case範例
<?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; }
-
while, do while範例
<?php while ($expr) { // structure body do { // structure body; } while ($expr);
-
for範例
<?php for ($i = 0; $i < 10; $i++) { // for body }
-
foreach範例
<?php foreach ($iterable as $key => $value) { // foreach body }
-
try, catch範例
<?php try { // try body } catch (FirstExceptionType $e) { // catch body } catch (OtherExceptionType $e) { // catch body }
###封閉性(Closures)
-
function後務必(MUST)有一個空格;use的前後務必(MUST)有一個空格
-
左大括弧
{
務必(MUST)和function關鍵字同行;右大括弧}
務必(MUST)獨自一行 -
左括弧
(
後務必不要(MUST Not)有一個空格;右括弧)
前務必不要(MUST Not)有一個空格 -
參數list或變數list中的逗號前務必不要(MUST Not)有一個空格,逗號後務必(MUST)要有一個空格
-
參數的預設值務必(MUST)放在參數list的最後一個
<?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body };
-
參數list和變數list可以斷行,但每個參數或變數都要斷行(含第一個)並要縮排一次。每行只能有一個參數
<?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 };
-
封閉性也可直接作為Method or Function的一個參數
<?php $foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 );
#PSR-3 Logger Interface
##1. PSR-3 總覽(待續)
#PSR-4 Autoloading
##1. PSR-4 總覽
###這部分看官方文件容易混淆,主要知道namespace(以\Acme\Log\Writer\File_Writer為例) 如下3點規則:
1. 前半部要和資料夾名稱一樣
\Acme\Log == ./acme-log/
或
\Acme\Log\ == ./acme/log/
2. 次資料夾名稱要和資料夾名稱一樣
\Acme\Log\Writer == ./acme-log/src/writer
(不要懷疑,中間可以有未宣告在namespace的次資料夾)
或
\Acme\Log\Writer == ./acme/log/writer
3. 最後的class名稱要和檔名一樣
\File_Writer == File_Writer.php
###規格
-
Class一詞包含classes, interfacesm traits和其他類似結構
-
一個合格的class name如下所示:
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
-
合格class name務必(MUST)要有一個top-level namespace name, 亦可稱作vendor namespace.
-
合格class name也許(MAY)有一個以上sub-namespace names.
-
合格class name務必(MUST)要有一個最終結尾的class name
-
底線(underscore)在合格class name的任一部分都沒有特定意義
-
縮寫字在合格class name也許(MAY)為大小寫的任意組合
-
所有class names務必(MUST)以case-sensitive風格來參照
-
-
當根據一合格class name載檔時
-
合格class name(namespace前綴)中,連續一個或多個開頭namespace & sub-namespace names裡,
不含開頭namespace separator,至少要和主資料夾(base directory)的其中一個名稱相同。 -
在namespace前綴後的連續sub-namespace names要和主資料夾(base directory)的次資料夾(subdirectory)名稱一樣。 在此name separators代表directory separators.
次資料夾(subdirectory)務必(MUST)和sub-namespace名稱大小寫完全一樣 -
最終結尾之class name要和
.php
的檔案名稱完全一樣。
-
-
Autoloader實作務必不要(MUST Not)丟例外(exception),
務必不要(MUST Not)給任何層次的errors,
最好不要(Should Not)return值。
###範例
完全合格class name | NAMESPACE 前綴 | 主資料夾(BASE DIRECTORY) | 產生的檔案路徑 |
---|---|---|---|
\Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php |
\Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php |
\Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php |
\Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php |