首页 > 代码库 > 我也学php:编码规范/翻译自PSR
我也学php:编码规范/翻译自PSR
PHP社区百花齐放,拥有大量的函数库、框架和组件。PHP开发者通常会在自己的项目中使用若干个外部库,因而PHP代码遵循或尽量接近同一个代码风格就非常重要,可以让开发者方便地把多个代码库集成在自己的项目中。
框架互操作组(即PHP标准组)发布了一系列代码风格推荐标准,即PSR-0,PSR-1,PSR-2和PSR-3。 不要让这些名称所混淆,这些推荐仅是一些被其它项目所遵循的规则,如Drupal, Zend, Symfony, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium等,你可以把这些规则用在自己的项目中,或者继续使用你自己的风格。
通常情况下,你的PHP代码应该遵循其中一项或多项标准,从而其他开发者可以方便地阅读和使用你的代码。这些标准都是在前一个标准 上附加新的规则,所以使用PSR-1就同时要求遵循PSR-0,但可以不遵循PSR-2。
可以使用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函数能够根据完整的类名从硬盘中自动加载指定的类文件,其中涉及到的“强制”要求有以下几点:
完整的namespace和class命名必须符合结构:\<Vendor Name>\(<Namespace>\)*<Class Name>.php
Vendor Name(开发者信息)必须是最顶层的namespace,这样可以防止自己类库与其他开发者类库出现命名冲突
(<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
PSR-1:简单编码规范
原文中的 "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(小写骆驼拼写法)
PSR-2:编码风格
针对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:日志接口
PSR-3是关于系统日志的接口的开发规范,先不翻译,后面复习php日志处理再回来翻译
链接:https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
我也学php:编码规范/翻译自PSR