本指南是 PSR-1 基本編碼標準 的擴充。
本指羅列了通用的PHP代碼格式規則和建議,意在減少不同作者的編碼風格差異所帶來的認知障礙。
這裡的風格約定衍生自若干成員項目。指南作者們在多個專案中協作,推動了這些指導條款落地。 指南的關鍵在於共享,而不是規則本身。
文中涉及的關鍵字「MUST 必須」, “MUST NOT 必須不”, “REQUIRED 必需”, “SHALL 會”, “SHALL NOT 不會”, “SHOULD 應該”, “SHOULD NOT 不應該”, “RECOMMENDED建議的”, “MAY 可能”, 和“OPTIONAL 可選的” 在RFC 2119 中有具體描述.
概覽
例子
下面是一個綜合的例子,可以幫助你對規則有一個概略的認識。
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span>use</span><span>FooInterface</span>; <span>use</span><span>BarClass</span><span>as</span><span>Bar</span>; <span>use</span><span>OtherVendor</span>\<span>OtherPackage</span>\<span>BazClass</span>; <span><span>class</span><span>Foo</span><span>extends</span><span>Bar</span><span>implements</span><span>FooInterface</span> {</span><span>public</span><span><span>function</span><span>sampleFunction</span><span>(<span>$a</span>, <span>$b</span> = null)</span> {</span><span>if</span> (<span>$a</span> === <span>$b</span>) { bar(); } <span>elseif</span> (<span>$a</span> > <span>$b</span>) { <span>$foo</span>->bar(<span>$arg1</span>); } <span>else</span> { BazClass::bar(<span>$arg2</span>, <span>$arg3</span>); } } <span>final</span><span>public</span><span>static</span><span><span>function</span><span>bar</span><span>()</span> {</span><span>// 方法 body</span> } }</span></code>
基本規則
基本編碼標準
代碼必須遵循PSR-1的條款。
檔案
行
縮排
注意:只使用空格,不用tab,有助於避免diffs,patches, history和annotations的問題。使用空格也有助於對齊。
關鍵字(保留字) 和true/false/null
Namespace 和Use 聲明必須有聲明
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span>use</span><span>FooClass</span>; <span>use</span><span>BarClass</span><span>as</span><span>Bar</span>; <span>use</span><span>OtherVendor</span>\<span>OtherPackage</span>\<span>BazClass</span>; <span>// ... additional PHP code ...</span></code>
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span>use</span><span>FooClass</span>; <span>use</span><span>BarClass</span><span>as</span><span>Bar</span>; <span>use</span><span>OtherVendor</span>\<span>OtherPackage</span>\<span>BazClass</span>; <span><span>class</span><span>ClassName</span><span>extends</span><span>ParentClass</span><span>implements</span> \<span>ArrayAccess</span>, \<span>Countable</span> {</span><span>// constants, properties, methods</span> }</code>
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span>use</span><span>FooClass</span>; <span>use</span><span>BarClass</span><span>as</span><span>Bar</span>; <span>use</span><span>OtherVendor</span>\<span>OtherPackage</span>\<span>BazClass</span>; <span><span>class</span><span>ClassName</span><span>extends</span><span>ParentClass</span><span>implements</span> \<span>ArrayAccess</span>, \<span>Countable</span>, \<span>Serializable</span> {</span><span>// constants, properties, methods</span> }</code>
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span><span>class</span><span>ClassName</span> {</span><span>public</span><span>$foo</span> = <span>null</span>; }</code>
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span><span>class</span><span>ClassName</span> {</span><span>public</span><span><span>function</span><span>fooBarBaz</span><span>(<span>$arg1</span>, &<span>$arg2</span>, <span>$arg3</span> = [])</span> {</span><span>// method body</span> } }</code>
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span><span>class</span><span>ClassName</span> {</span><span>public</span><span><span>function</span><span>foo</span><span>(<span>$arg1</span>, &<span>$arg2</span>, <span>$arg3</span> = [])</span> {</span><span>// method body</span> } }</code>
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span><span>class</span><span>ClassName</span> {</span><span>public</span><span><span>function</span><span>aVeryLongMethodName</span><span>( ClassTypeHint <span>$arg1</span>, &<span>$arg2</span>, array <span>$arg3</span> = [] )</span> {</span><span>// method body</span> } }</code>
static聲明必須在可見性之後。
<code><span><?php</span><span>namespace</span><span>Vendor</span>\<span>Package</span>; <span>abstract</span><span><span>class</span><span>ClassName</span> {</span><span>protected</span><span>static</span><span>$foo</span>; <span>abstract</span><span>protected</span><span><span>function</span><span>zim</span><span>()</span>;</span><span>final</span><span>public</span><span>static</span><span><span>function</span><span>bar</span><span>()</span> {</span><span>// method body</span> } }</code>
写方法或函数调用时,方法/函数名 和 左括号( 之间,必须没有空格, 右括号 ) 之前必须没有空格。在参数列表中,逗号间必须没有逗号,每个逗号后必须有一个空格。
<code><span><?php</span><span>$foo</span>->bar( <span>$longArgument</span>, <span>$longerArgument</span>, <span>$muchLongerArgument</span> );</span></code>
控制结构
控制结构通常遵循以下风格:
if, elseif, else
if 结构如下所示。注意括号、空格、花括号的位置;同时留意 else 和 elseif 与前一部分的 } 在同一行。
<code><span><?php</span><span>if</span> (<span>$expr1</span>) { <span>// if body</span> } <span>elseif</span> (<span>$expr2</span>) { <span>// elseif body</span> } <span>else</span> { <span>// else body;</span> }</code>
elseif关键字不应该被 else if 代替。
switch, case
Switch结构如下所示。注意括号、空格和花括号的位置。 case 语句相对于switch必须有一个缩进, break关键字 或者其他终结性的关键字必须和case body在同一缩进层级。在非空的case body,如果没有终结性语句,必须加上注释 // no break
。
<code><span><?php</span><span>switch</span> (<span>$expr</span>) { <span>case</span><span>0</span>: <span>echo</span><span>'First case, with a break'</span>; <span>break</span>; <span>case</span><span>1</span>: <span>echo</span><span>'Second case, which falls through'</span>; <span>// no break</span><span>case</span><span>2</span>: <span>case</span><span>3</span>: <span>case</span><span>4</span>: <span>echo</span><span>'Third case, return instead of break'</span>; <span>return</span>; <span>default</span>: <span>echo</span><span>'Default case'</span>; <span>break</span>; }</code>
while, do while
while结构如下所示。 注意括号、空格和花括号的位置。
<code><span><?php</span><span>while</span> (<span>$expr</span>) { <span>// structure body</span> }</code>
do-while接口如下所示。 注意括号、空格和花括号的位置。
<code><span><?php</span><span>do</span> { <span>// structure body;</span> } <span>while</span> (<span>$expr</span>);</code>
for
for 结构如下所示。 注意括号、空格和花括号的位置。
<code><span><?php</span><span>for</span> (<span>$i</span> = <span>0</span>; <span>$i</span> < <span>10</span>; <span>$i</span>++) { <span>// for body</span> }</code>
foreach
foreach 结构如下所示。 注意括号、空格和花括号的位置。
<code><span><?php</span><span>foreach</span> (<span>$iterable</span><span>as</span><span>$key</span> => <span>$value</span>) { <span>// foreach body</span> }</span></code>
try, catch
try-catch区块如下所示。 注意括号、空格和花括号的位置。
<code><span><?php</span><span>try</span> { <span>// try body</span> } <span>catch</span> (FirstExceptionType <span>$e</span>) { <span>// catch body</span> } <span>catch</span> (OtherExceptionType <span>$e</span>) { <span>// catch body</span> }</code>
Closure 闭包
声明闭包必须在function关键字后留一个空格,在use关键字前后各留一个空格。
左花括号必须在同一行, 右花括号必须在body的下一行。
参数或变量列表的左括号后 和 右括号前必须没有空格。
参数和变量列表的逗号前必须没有空格,每个逗号后必须有一个空格。
有默认值的参数必须排在最后。
闭包的声明如下所示。 注意括号,逗号,空格和花括号的位置:
<code><span><?php</span><span>$closureWithArgs</span> = <span><span>function</span><span>(<span>$arg1</span>, <span>$arg2</span>)</span> {</span><span>// body</span> }; <span>$closureWithArgsAndVars</span> = <span><span>function</span><span>(<span>$arg1</span>, <span>$arg2</span>)</span><span>use</span><span>(<span>$var1</span>, <span>$var2</span>)</span> {</span><span>// body</span> };</code>
参数列表和变量列表可以拆分到多行,每个子行有一层缩进。 这么做的时候,第一个列表成员必须独占一行,每行只能有一个列表成员。
参数或变量列表拆分为多行时,到了列表的末尾, 右括号 和 左花括号必须放在同一行,中间有一个空格。
例子:
<code><span><?php</span><span>$longArgs_noVars</span> = <span><span>function</span><span>( <span>$longArgument</span>, <span>$longerArgument</span>, <span>$muchLongerArgument</span> )</span> {</span><span>// body</span> }; <span>$noArgs_longVars</span> = <span><span>function</span><span>()</span><span>use</span><span>( <span>$longVar1</span>, <span>$longerVar2</span>, <span>$muchLongerVar3</span> )</span> {</span><span>// body</span> }; <span>$longArgs_longVars</span> = <span><span>function</span><span>( <span>$longArgument</span>, <span>$longerArgument</span>, <span>$muchLongerArgument</span> )</span><span>use</span><span>( <span>$longVar1</span>, <span>$longerVar2</span>, <span>$muchLongerVar3</span> )</span> {</span><span>// body</span> }; <span>$longArgs_shortVars</span> = <span><span>function</span><span>( <span>$longArgument</span>, <span>$longerArgument</span>, <span>$muchLongerArgument</span> )</span><span>use</span><span>(<span>$var1</span>)</span> {</span><span>// body</span> }; <span>$shortArgs_longVars</span> = <span><span>function</span><span>(<span>$arg</span>)</span><span>use</span><span>( <span>$longVar1</span>, <span>$longerVar2</span>, <span>$muchLongerVar3</span> )</span> {</span><span>// body</span> };</code>
注意:当闭包被直接作为函数或方法调用的参数时,以上规则同样适用。
<code><span><?php</span><span>$foo</span>->bar( <span>$arg1</span>, <span><span>function</span><span>(<span>$arg2</span>)</span><span>use</span><span>(<span>$var1</span>)</span> {</span><span>// body</span> }, <span>$arg3</span> );</span></code>
结语
本指南刻意忽略了许多风格和实践。包括但不限于:
Future recommendations MAY revise and extend this guide to address those or other elements of style and practice.
附录A 调查
In writing this style guide, the group took a survey of member projects to determine common practices. The survey is retained herein for posterity.
调查数据
<code>url,<span>http</span>:<span>//</span>www.horde.org<span>/apps/horde/docs/CODING_STANDARDS,http:/</span><span>/pear.php.net/manual/en/standards.php,http:/</span><span>/solarphp.com/manual/appendix-standards.style,http:/</span><span>/framework.zend.com/manual/en/coding-standard.html,http:/</span><span>/symfony.com/doc/2.0/contributing/code/standards.html,http:/</span><span>/www.ppi.io/docs/coding-standards.html,https:/</span><span>/github.com/ezsystems/ezp-next/wiki/codingstandards,http:/</span><span>/book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html,https:/</span><span>/github.com/UnionOfRAD/lithium/wiki/Spec%3A-Coding,http:/</span><span>/drupal.org/coding-standards,http:/</span><span>/code.google.com/p/sabredav/</span>,<span>http</span>:<span>//</span>area51.phpbb.com<span>/docs/31x/coding-guidelines.html,https:/</span><span>/docs.google.com/a/zikula.org/document/edit?authkey=CPCU0Us&hgd=1&id=1fcqb93Sn-hR9c0mkN6m_tyWnmEvoswKBtSc0tKkZmJA,http:/</span><span>/www.chisimba.com,n/a,https:/</span><span>/github.com/Respect/project-info/blob/master/coding-standards-sample.php,n/a,Object Calisthenics for PHP,http:/</span><span>/doc.nette.org/en/coding-standard,http:/</span><span>/flow3.typo3.org,https:/</span><span>/github.com/propelorm/Propel2/wiki/Coding-Standards,http:/</span>/developer.joomla.org/coding-standards.html voting,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>no</span>,<span>no</span>,?,<span>yes</span>,<span>no</span>,<span>yes</span> indent_type,<span>4</span>,<span>4</span>,<span>4</span>,<span>4</span>,<span>4</span>,tab,<span>4</span>,tab,tab,<span>2</span>,<span>4</span>,tab,<span>4</span>,<span>4</span>,<span>4</span>,<span>4</span>,<span>4</span>,<span>4</span>,tab,tab,<span>4</span>,tab line_length_limit_soft,<span>75</span>,<span>75</span>,<span>75</span>,<span>75</span>,<span>no</span>,<span>85</span>,<span>120</span>,<span>120</span>,<span>80</span>,<span>80</span>,<span>80</span>,<span>no</span>,<span>100</span>,<span>80</span>,<span>80</span>,?,?,<span>120</span>,<span>80</span>,<span>120</span>,<span>no</span>,<span>150</span> line_length_limit_hard,<span>85</span>,<span>85</span>,<span>85</span>,<span>85</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>100</span>,?,<span>no</span>,<span>no</span>,<span>no</span>,<span>100</span>,<span>100</span>,?,<span>120</span>,<span>120</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span> class_names,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,lower_under,studly,lower,studly,studly,studly,studly,?,studly,studly,studly class_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,next,next,next,next,next,next,same,next,next constant_names,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper true_false_null,lower,lower,lower,lower,lower,lower,lower,lower,lower,upper,lower,lower,lower,upper,lower,lower,lower,lower,lower,upper,lower,lower method_names,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,lower_under,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel method_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,same,next,next,next,next,next,same,next,next control_brace_line,same,same,same,same,same,same,next,same,same,same,same,next,same,same,next,same,same,same,same,same,same,next control_space_after,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span> always_use_control_braces,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span>,<span>yes</span> else_elseif_line,same,same,same,same,same,same,next,same,same,next,same,next,same,next,next,same,same,same,same,same,same,next case_break_indent_from_switch,<span>0</span>/<span>1</span>,<span>0</span>/<span>1</span>,<span>0</span>/<span>1</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>1</span>,<span>1</span>/<span>1</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>1</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span>,<span>0</span>/<span>1</span>,<span>1</span>/<span>1</span>,<span>1</span>/<span>2</span>,<span>1</span>/<span>2</span> function_space_after,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span> closing_php_tag_required,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,<span>no</span>,<span>no</span> line_endings,LF,LF,LF,LF,LF,LF,LF,LF,?,LF,?,LF,LF,LF,LF,?,,LF,?,LF,LF,LF static_or_visibility_first,static,?,static,either,either,either,visibility,visibility,visibility,either,static,either,?,visibility,?,?,either,either,visibility,visibility,static,? control_space_parens,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,?,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span> blank_line_after_php,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>no</span>,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>no</span>,<span>yes</span>,?,<span>yes</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>no</span>,<span>yes</span>,<span>no</span> class_method_control_brace,next/next/same,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/next,same/same/same,same/same/same,same/same/same,same/same/same,next/next/next,next/next/same,next/same/same,next/next/next,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/same,next/next/next</code>
调查说明
indent_type: The type of indenting. tab = “Use a tab”, 2 or 4 = “number of spaces”
line_length_limit_soft: The “soft” line length limit, in characters. ? = not discernible or no response, no means no limit.
line_length_limit_hard: The “hard” line length limit, in characters. ? = not discernible or no response, no means no limit.
class_names: How classes are named. lower = lowercase only, lower_under = lowercase with underscore separators, studly = StudlyCase.
class_brace_line: Does the opening brace for a class go on the same line as the class keyword, or on the next line after it?
constant_names: How are class constants named? upper = Uppercase with underscore separators.
true_false_null: Are the true, false, and null keywords spelled as all lower case, or all upper case?
method_names: How are methods named? camel = camelCase, lower_under = lowercase with underscore separators.
method_brace_line: Does the opening brace for a method go on the same line as the method name, or on the next line?
control_brace_line: Does the opening brace for a control structure go on the same line, or on the next line?
control_space_after: Is there a space after the control structure keyword?
always_use_control_braces: Do control structures always use braces?
else_elseif_line: When using else or elseif, does it go on the same line as the previous closing brace, or does it go on the next line?
case_break_indent_from_switch: How many times are case and break indented from an opening switch statement?
function_space_after: Do function calls have a space after the function name and before the opening parenthesis?
closing_php_tag_required: In files containing only PHP, is the closing ?> tag required?
line_endings: What type of line ending is used?
static_or_visibility_first: When declaring a method, does static come first, or does the visibility come first?
control_space_parens: In a control structure expression, is there a space after the opening parenthesis and a space before the closing parenthesis? yes = if (
blank_line_after_php: Is there a blank line after the opening PHP tag?
class_method_control_brace: A summary of what line the opening braces go on for classes, methods, and control structures.
调查结果
<code><span>indent_type:</span> tab: <span>7</span><span>2</span>: <span>1</span><span>4</span>: <span>14</span><span>line_length_limit_soft:</span> ?: <span>2</span> no: <span>3</span><span>75</span>: <span>4</span><span>80</span>: <span>6</span><span>85</span>: <span>1</span><span>100</span>: <span>1</span><span>120</span>: <span>4</span><span>150</span>: <span>1</span><span>line_length_limit_hard:</span> ?: <span>2</span> no: <span>11</span><span>85</span>: <span>4</span><span>100</span>: <span>3</span><span>120</span>: <span>2</span><span>class_names:</span> ?: <span>1</span> lower: <span>1</span> lower_under: <span>1</span> studly: <span>19</span><span>class_brace_line:</span> next: <span>16</span> same: <span>6</span><span>constant_names:</span> upper: <span>22</span><span>true_false_null:</span> lower: <span>19</span> upper: <span>3</span><span>method_names:</span> camel: <span>21</span> lower_under: <span>1</span><span>method_brace_line:</span> next: <span>15</span> same: <span>7</span><span>control_brace_line:</span> next: <span>4</span> same: <span>18</span><span>control_space_after:</span> no: <span>2</span> yes: <span>20</span><span>always_use_control_braces:</span> no: <span>3</span> yes: <span>19</span><span>else_elseif_line:</span> next: <span>6</span> same: <span>16</span><span>case_break_indent_from_switch:</span><span>0</span>/<span>1</span>: <span>4</span><span>1</span>/<span>1</span>: <span>4</span><span>1</span>/<span>2</span>: <span>14</span><span>function_space_after:</span> no: <span>22</span><span>closing_php_tag_required:</span> no: <span>19</span> yes: <span>3</span><span>line_endings:</span> ?: <span>5</span> LF: <span>17</span><span>static_or_visibility_first:</span> ?: <span>5</span> either: <span>7</span> static: <span>4</span> visibility: <span>6</span><span>control_space_parens:</span> ?: <span>1</span> no: <span>19</span> yes: <span>2</span><span>blank_line_after_php:</span> ?: <span>1</span> no: <span>13</span> yes: <span>8</span><span>class_method_control_brace:</span> next/next/next: <span>4</span> next/next/same: <span>11</span> next/same/same: <span>1</span> same/same/same: <span>6</span></code>
以上就介绍了PHP编码风格指南 (PHP-FIG PSR-2),包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。