[TOC=2] ## 1.概述 * 代码必须遵循“编码风格指南”PSR [ PSR-1 ]。 * 代码必须使用 4 个空格进行缩进,而不是制表符。 * 线路长度不得有硬性限制 ; 软限制必须是 120 个字符; 线条不应该是 80 个字符或更少。 * `namespace` 声明后必须有一个空行,并且在声明块之后必须有一个空行 `use`。 * 打开类的大括号必须在下一行,并且关闭大括号必须在主体后面的下一行。 * 打开方法的括号必须在下一行,并且关闭括号必须在主体后面的下一行。 * 必须在所有属性和方法上声明可见性 ; `abstract`并且 `final` 必须在能见度之前宣布 ; `static `必须在能见度后宣布。 * 控制结构关键字必须在它们之后有一个空格 ; 方法和函数调用绝不可以。 * 控制结构的开口括号必须在同一条线上,并且关闭括号必须在主体后面的下一行。 * 控制结构的开括号必须在它们后面没有空格,并且控制结构的右括号之前不能有空格。 ### 1.1 例 此示例包含以下一些规则作为快速概述: ~~~php <?php namespace Vendor\Package; use FooInterface; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class Foo extends Bar implements FooInterface { public function sampleMethod($a, $b = null) { if ($a === $b) { bar(); } elseif ($a > $b) { $foo->bar($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body } } ~~~ ## 2.一般 ### 2.1 基本编码标准 * 代码必须遵循 PSR-1 中列出的所有规则。 ### 2.2 档 * 所有 PHP 文件必须使用 Unix LF(换行)行结尾。 * 所有 PHP 文件必须以一个空行结束。 * `?>` 必须从仅包含 PHP 的文件中省略结束标记。 ### 2.3 行 * 线路长度不得有硬性限制。 * 线路长度的软限制必须是 120 个字符 ; 自动样式检查器必须发出警告 , 但绝不能在软限制上出错。 * 行不应超过 80 个字符 ; 超过的行应该被分成多个后续行,每行不超过 80 个字符。 * 在非空白行的末尾不得有尾随空格。 * 可以添加空行以提高可读性并指示相关的代码块。 * 每行不得超过一个语句。 ### 2.4 缩进 * 代码必须使用 4 个空格的缩进,并且不得使用制表符进行缩进。 Nb:仅使用空格,而不是将空格与制表符混合,有助于避免差异,补丁,历史记录和注释的问题 。空间的使用还使得易于插入细粒度的子压痕用于线间对齐。 ### 2.5 关键字和真/假/空 * PHP 关键字必须是小写的。 * PHP 的常量 true ,false 以及 null 必须是小写。 ## 3.命名空间和使用声明 * 如果存在, `namespace` 声明后必须有一个空行。 * 如果存在,所有 `use` 声明必须在 `namespace`声明之后。 * `use` 每个声明必须有一个关键字。 * 在 `use` 块之后必须有一个空白行。 例如: ~~~php <?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; // ... additional PHP code ... ~~~ ## 4.类,属性和方法 * 术语“class”指的是所有类,接口和特征。 ### 4.1 扩展和实施 * 在 `extends` 和 `implements` 关键字必须在同一行中声明的类名。 * 班级的开口支架必须自成一线; 班级的结束括号必须在身体后面的下一行。 ~~~php <?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable { // constants, properties, methods } ~~~ * `implementsMAY` 列表分为多行,每行后续行缩进一次。这样做时,列表中的第一项必须在下一行,并且每行必须只有一个接口。 ~~~php <?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 } ~~~ ### 4.2 属性 * 必须在所有属性上声明可见性。 * 该 `var` 关键字不能被用于声明属性。 * 每个语句不得超过一个属性。 * 属性名称不应以单个下划线为前缀,以表示受保护或私有可见性。 属性声明如下所示。 ~~~php <?php namespace Vendor\Package; class ClassName { public $foo = null; } ~~~ ### 4.3 方法 * 必须在所有方法上声明可见性。 * 方法名称不应以单个下划线为前缀,以指示受保护或私有可见性。 * 方法名称不得在方法名称后面用空格声明。在括弧必须继续自己的路线,和右括号必须继续下去了下一行后的身体。在左括号后面不能有空格,并且在右括号之前不能有空格。 方法声明如下所示。请注意 括号,逗号,空格和大括号的位置: ~~~php <?php namespace Vendor\Package; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } } ~~~ ### 4.4 方法参数 * 在参数列表中,每个逗号前不得有空格,每个逗号后必须有一个空格。 * 具有默认值的方法参数必须位于参数列表的末尾。 ~~~php <?php namespace Vendor\Package; class ClassName { public function foo($arg1, &$arg2, $arg3 = []) { // method body } } ~~~ * 参数列表可以分为多行,每行后续行缩进一次。这样做时,列表中的第一项必须在下一行,并且每行必须只有一个参数。 * 当参数列表分成多行时,右括号和左括号必须放在一起,它们各自之间有一个空格。 ~~~php <?php namespace Vendor\Package; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body } } ~~~ ### 4.5 abstract , final , and static * 如果存在,`abstract` 并 `final` 声明必须先于知名度声明。 * 如果存在, `static` 声明必须在可见性声明之后。 ~~~php <?php namespace Vendor\Package; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } } ~~~ ### 4.6 方法和函数调用 * 在进行方法或函数调用时,方法或函数名称与左括号之间不能有空格,在左括号后面不能有空格,并且在右括号之前不能有空格。在参数列表中,每个逗号前不得有空格,每个逗号后必须有一个空格。 ~~~php <?php bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3); ~~~ * 参数列表可以分为多行,每行后续行缩进一次。这样做时,列表中的第一项必须在下一行,并且每行必须只有一个参数。 ~~~php <?php $foo->bar( $longArgument, $longerArgument, $muchLongerArgument ); ~~~ ## 5.控制结构 控制结构的一般样式规则如下: * 控制结构关键字后面必须有一个空格 * 在左括号后面不能有空格 * 在右括号之前不能有空格 * 在右括号和左括号之间必须有一个空格 * 结构体必须缩进一次 * 闭合支撑必须在身体后面的下一行 * 每个结构的主体必须用括号括起来。这标准化了结构的外观,并减少了在新线被添加到身体时引入错误的可能性。 ### 5.1 if,elseif,else if 结构如下所示。注意括号,空格和大括号的位置; 并且else与 早期身体elseif的右大括号位于同一条线上。 ~~~php <?php if ($expr1) { // if body } elseif ($expr2) { // elseif body } else { // else body; } ~~~ elseif 该使用关键字而不是 else if 所有控件关键字看起来像单个单词。 ### 5.2 switch,case 一个 switch 结构如下所示。请注意括号,空格和大括号的位置。的 case 语句必须一次缩进从 switch 和 break 关键字(或其它终端关键字)必须在相同的水平缩进 case 机构。必须有一个评论,例如 ~~~php // no break在非空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; } ~~~ ### 5.3 while, do while 一个 while 声明如下所示。请注意括号,空格和大括号的位置。 ~~~php <?php while ($expr) { // structure body } ~~~ 同样,do while语句如下所示。请注意括号,空格和大括号的位置。 ~~~php <?php do { // structure body; } while ($expr); ~~~ ### 5.4 for 一个 for 声明如下所示。请注意括号,空格和大括号的位置。 ~~~php <?php for ($i = 0; $i < 10; $i++) { // for body } ~~~ ### 5.5 foreach 一个 foreach 声明如下所示。请注意括号,空格和大括号的位置。 ~~~php <?php foreach ($iterable as $key => $value) { // foreach body } ~~~ ### 5.6 try catch 一个 try catch 块如下所示。请注意括号,空格和大括号的位置。 ~~~php <?php try { // try body } catch (FirstExceptionType $e) { // catch body } catch (OtherExceptionType $e) { // catch body } ~~~ ## 6.关闭 * 闭包必须在 function 关键字后面用空格声明,并在关键字前后加一个空格 use。 * 开口支撑必须在同一条线上,并且闭合支撑必须在身体后面的下一行。 * 在参数列表或变量列表的左括号之后不能有空格,并且在参数列表或变量列表的右括号之前不能有空格。 * 在参数列表和变量列表中,每个逗号前不能有空格,每个逗号后必须有一个空格。 * 具有默认值的闭包参数必须位于参数列表的末尾。 闭包声明如下所示。请注意括号,逗号,空格和大括号的位置: ~~~php <?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body }; ~~~ * 参数列表和变量列表可以分为多行,每行后续行缩进一次。这样做时,列表中的第一项必须在下一行,并且每行必须只有一个参数或变量。 * 当结束列表(无论是参数还是变量)被分割成多行时,右括号和左括号必须放在一起,并且它们之间有一个空格。 以下是包含和不包含参数列表的闭包的示例,以及跨多行分割的变量列表。 ~~~php <?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 }; ~~~ >[danger] 请注意,当函数或方法调用中的闭包直接用作参数时,格式设置规则也适用。 ~~~php <?php $foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 ); ~~~ ## 7.结论 * 本指南有意省略了许多风格和实践元素。这些包括但不限于: * 全局变量和全局常量的声明 * 职能宣言 * 运营商和任务 * 线间对齐 * 评论和文档块 * 类名前缀和后缀 最佳做法 未来的建议可能会修订和扩展本指南,以解决风格和实践中的那些或其他元素。 ## 附录A 调查 在撰写本风格指南时,该小组对成员项目进行了调查,以确定常见做法。该调查在此保留给后人。 ### A.1 调查数据 ~~~php url,http://www.horde.org/apps/horde/docs/CODING_STANDARDS,http://pear.php.net/manual/en/standards.php,http://solarphp.com/manual/appendix-standards.style,http://framework.zend.com/manual/en/coding-standard.html,https://symfony.com/doc/2.0/contributing/code/standards.html,http://www.ppi.io/docs/coding-standards.html,https://github.com/ezsystems/ezp-next/wiki/codingstandards,http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html,https://github.com/UnionOfRAD/lithium/wiki/Spec%3A-Coding,http://drupal.org/coding-standards,http://code.google.com/p/sabredav/,http://area51.phpbb.com/docs/31x/coding-guidelines.html,https://docs.google.com/a/zikula.org/document/edit?authkey=CPCU0Us&hgd=1&id=1fcqb93Sn-hR9c0mkN6m_tyWnmEvoswKBtSc0tKkZmJA,http://www.chisimba.com,n/a,https://github.com/Respect/project-info/blob/master/coding-standards-sample.php,n/a,Object Calisthenics for PHP,http://doc.nette.org/en/coding-standard,http://flow3.typo3.org,https://github.com/propelorm/Propel2/wiki/Coding-Standards,http://developer.joomla.org/coding-standards.html voting,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,no,no,no,?,yes,no,yes indent_type,4,4,4,4,4,tab,4,tab,tab,2,4,tab,4,4,4,4,4,4,tab,tab,4,tab line_length_limit_soft,75,75,75,75,no,85,120,120,80,80,80,no,100,80,80,?,?,120,80,120,no,150 line_length_limit_hard,85,85,85,85,no,no,no,no,100,?,no,no,no,100,100,?,120,120,no,no,no,no 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,yes,yes,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes always_use_control_braces,yes,yes,yes,yes,yes,yes,no,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes 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,0/1,0/1,0/1,1/2,1/2,1/2,1/2,1/1,1/1,1/2,1/2,1/1,1/2,1/2,1/2,1/2,1/2,1/2,0/1,1/1,1/2,1/2 function_space_after,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no closing_php_tag_required,no,no,no,no,no,no,no,no,yes,no,no,no,no,yes,no,no,no,no,no,yes,no,no 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,no,no,no,no,no,no,yes,no,no,no,no,no,no,yes,?,no,no,no,no,no,no,no blank_line_after_php,no,no,no,no,yes,no,no,no,no,yes,yes,no,no,yes,?,yes,yes,no,yes,no,yes,no 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 ~~~ ### A2 调查传奇 1. indent_type:缩进的类型。tab=“使用标签”,2或4=“空格数” 2. line_length_limit_soft:“软”行长度限制,以字符为单位。?= 无法辨别或没有回应,no 意味着没有限制。 3. line_length_limit_hard:“硬”行长度限制,以字符为单位。?= 无法辨别或没有回应,no 意味着没有限制。 4. class_names:如何命名类。lower= 仅小写,lower_under= 带下划线分隔符的小写,studly = StudlyCase。 5. class_brace_line:一个类的左括号是 same 作为 class 关键字 next 在行上还是在它之后的行上? 6. constant_names:类常量如何命名?upper= 带有下划线分隔符的大写。 7. true_false_null:是 true ,false 和 null 关键字拼写为所有的 lower 情况下,或所有 upper 的情况下? 8. method_names:如何命名方法 ?camel = camelCase,lower_under= 带下划线分隔符的小写。 9. method_brace_line:方法的左括号是 same 作为方法名称还是 next 在行上? 10. control_brace_line:控制结构的开口支撑是 same 在线上还是 next 在线上? 11. control_space_after:控制结构关键字后面是否有空格? 12. always_use_control_braces:控制结构总是使用大括号吗? 13. else_elseif_line:当使用 else 或时 elseif ,它是否 same 作为前一个右大括号上 next 线,还是上线? 14. case_break_indent_from_switch:有多少时间 case 和 break 从开口缩进 switch 声明? 15. function_space_after:函数调用在函数名后面和左括号之前是否有空格? 16. closing_php_tag_required:在仅包含 PHP 的文件中,是否 `?>` 需要结束标记? 17. line_endings:使用什么类型的行结尾? 18. static_or_visibility_first:当声明一个方法时,确实 static 是第一个,或者可见性是第一个? 19. control_space_parens:在控制结构表达式中,左括号后面是空格还是右括号前有空格?yes= if ( $expr ),no= if ($expr)。 20. blank_line_after_php:打开 PHP 标记后是否有空行? 21. class_method_control_brace:关于类,方法和控制结构的开头括号的内容摘要。 ### A.3 调查结果 1. indent_type: tab: 7 2: 1 4: 14 2. line_length_limit_soft: ?: 2 no: 3 75: 4 80: 6 85: 1 100: 1 120: 4 150: 1 3. line_length_limit_hard: ?: 2 no: 11 85: 4 100: 3 120: 2 4. class_names: ?: 1 lower: 1 lower_under: 1 studly: 19 5. class_brace_line: next: 16 same: 6 6. constant_names: upper: 22 7. true_false_null: lower: 19 upper: 3 8. method_names: camel: 21 lower_under: 1 9. method_brace_line: next: 15 same: 7 10. control_brace_line: next: 4 same: 18 11. control_space_after: no: 2 yes: 20 12. always_use_control_braces: no: 3 yes: 19 13. else_elseif_line: next: 6 same: 16 14. case_break_indent_from_switch: 0/1: 4 1/1: 4 1/2: 14 15. function_space_after: no: 22 16. closing_php_tag_required: no: 19 yes: 3 17. line_endings: ?: 5 LF: 17 18. static_or_visibility_first: ?: 5 either: 7 static: 4 visibility: 6 19. control_space_parens: ?: 1 no: 19 yes: 2 20. blank_line_after_php: ?: 1 no: 13 yes: 8 21. class_method_control_brace: next/next/next: 4 next/next/same: 11 next/same/same: 1 same/same/same: 6