这篇文章记录一下PHP的编程代码规范,做一个规范的PHPer。

PSR:即PHP Standards recommendation(PHP推荐标准)。

PSR-1:基本的代码风格

  • PHP标签: PHP标签只使用<?php ?>和<?= ?>,不得使用其他PHP标签句法。
  • 编码: PHP所有文件都必须使用UTF-8字符集编码。
  • 目的: 一个PHP文件可以定义符号(类、性状、函数和常量),或者执行有副作用的操作(例如,生成结果或处理数据),但是不能同时做这两件事。
  • 自动加载: PHP命名空间和类必须遵守PSR-4自动加载器标准。
  • 类的名称: PHP类的名称必须使用CamelCase这种驼峰式。
  • 常量的名称:PHP常量的名称必须全部使用大写字母。如果需要,可以使用下划线把单词分开。例如:THIS_VARIABLE
  • 方法的命名: PHP方法的名称必须使用camelCase这种驼峰式,首字母是小写的,后续的所有单词的首字母都是大写的。如:phpIsAwesome

PSR-2:严格的代码风格

PSR-2是在PSR-1的基础上进一步的要求。

  • 缩进 PSR-2推荐的规范要求是使用4个空格缩进(因为空格最可靠,在不同的代码编辑器中渲染的效果基本一致)
  • 文件和代码 PHP文件的最后一行要有一个空行,而且不能使用PHP关闭标签?>,每行末尾都不能有空格。(这些要求大多数编辑器能帮你做好)

注:PHP文件不写关闭标签的目的是能避免意料之外的输出错误。如果加上关闭标签?>,而且在关闭标签后有空行。那么这个空行会被当成输出导致错误。(例如,设定HTTP头部时)

  • 关键字 对于ture,false和null,PSR-2推荐这些关键字都要使用小写字母的形式。
  • 命名空间 每个命名空间声明语句后面必须跟着一个空行。使用use关键字导入命名空间时,在一系列的use声明语句后要加一个空行。
  • 类 PSR-2推荐类定义体的起始括号应该在类名之后新起一行写。如下代码所示:
1
2
3
4
5
6
7

<?php

class example
{
//类的定义
}
  • 方法 (直接代码示例如下)
1
2
3
4
5
6
7
8
9
10
<?php
namespace Animals //注意这里的命名空间首字母需要大写

class example
{
public function test($params = 1, $params = 'two')//注意这里起始括号和结束括号两边都没有空格
{
//方法的定义
}
}
  • 可见性 类中的每个属性和方法都要声明可见性。abstractfinal这俩关键字要放在可见性关键字前面。static关键字要放在可见性关键字后面。代码如下
1
2
3
4
5
6
7
8
9
10

class example
{
public static $number = 0;

public function __construct()
{
static::$number++;
}
}
  • 控制结构 控制结构中如if else switch foreach等这些关键字后面都要有一个空格。示例代码如下
1
2
3
4
5
<?php

if (a == b){ //注意这里的花括号不用新起一行

}

虽然现在有挺多的编辑器支持根据PSR-1和PSR-2来格式化代码了,不过这些写代码中的规范还是需要记住一下,尽量让自己的代码风格规范一些,这样在日常的工作中也方便团队交流。

PSR-3:日志记录器接口

PSR-3与前面得规范不同,它是一个接口,规定PHP日志记录器组件可以实现得方法。

大多数PHP框架都在某种程度上实现了日志功能。为了实现互操作性和专业化,PHP-FIG制定了PSR-3日志记录器接口。若想使用符合PSR-3规范得日志记录器,框架要做到两件重要得事:日志功能委托给第三方库实现;最终用户能选择使用他们喜欢得日志记录器组件。

编写PSR-3日志记录器

符合PSR-3推荐规范的PHP日志记录器组件,必须包含一个实现Psr\Log|LoggerInterface接口得PHP类。PSR-3接口复用了系统日志协议,规定要实现以下九个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
namespace Psr\Log;

interface LoggerInterface
{
public function emergency($message,array $context = array());
public function alert($message,array $context = array());
public function critial($message,array $context = array());
public function error($message,array $context = array());
public function warning($message,array $context = array());
public function notice($message,array $context = array());
public function info($message,array $context = array());
public function debug($message,array $context = array());
public function log($level,$message,array $context = array());
}

但是,我们现在已经不需要自己去编写一个日志记录器了,因为已经有了Monolog(可访问packagist这个网站查看介绍)这个十分出色的PHP日志记录器组件了,它几乎提供了开发过程中所有需要的功能。

PSR-4:自动加载器

PSR-4描述了一个标准的自动加载器策略。自动加载器策略是指,在运行时按需查找PHP类、接口或者性状,并将其载入PHP解释器。支持PSR-4自动加载器标准的PHP组件和框架,使用同一个自动加载器就能找到相关代码

在PHP-FIG发布PSR-4推荐规范之前,PHP组件和框架的作者使用__autoload()spl_autoload_register()函数注册自定义的自动加载器策略。可是,每个PHP组件和框架都使用独特的自动加载器,而且每个加载器使用不同的逻辑查找并加载PHP类、性状和接口。使用这些组件和框架的开发者,在引导PHP应用时必须调用每个组件各自的自动加载器时必须调用每个组件各自的自动加载器。这样在开发中很麻烦。

如今,得益于PSR-4,我们只需要使用一个自动加载器就能自动加载应用中的所有PHP组件。大多数现代的PHP组件和框架都符合PSR-4规范。

PSR自动加载策略

PSR-4自动加载策略依赖PHP命名空间和文件系统目录结构查找并加载PHP类、接口,性状。

它的精髓是把命名空间的前缀和文件系统中的目录对应起来。例如,\Oreilly\ModernPHP\Chapter1命名空间对应与src/chapter1目录,\Oreilly\ModernPHP\Chapter1\Example类对应于src/Chapter1/Example

实现一个PSR-4自动加载器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
/**
* 该代码中,使用SPL注册这个自动加载函数后,遇到下述代码时,这个函数会
* 自动尝试从/path/to/project/src/Baz/Qux.php文件中加载
* \Foo\Bar\Baz\Quz类:
* new \Foo\Bar\Baz\Qux;
*
*/

spl_autpload_register(function ($class)){
//这个项目的命名空间前缀
$prefix = 'Foo\\Bar\\';

//这个命名空间对应的根目录;
$base_url = __DIR__.'/src/';

//参数传入的类使用这个命名空间前缀吗?
$len = strlen($prefix);
if(strncmp($prefix, $class, $len) !==0){
//不使用,交给注册的下一个自动加载器处理
return;
}

//获取去掉前缀后的类名
$relative_class = substr($class, $len);

//把命名空间前缀替换成根目录,
//去掉前缀的类命中,把命名空间分隔符替换成目录分隔符,
//然后再后面加上.php
$file = $base_dir.str_replace('\\', '/', $relative_class).'.php';

//如果文件存在,将其导入
if(file_exists($file)){
require $file;
}
}

以上代码是一个PSR-4自动加载器的逻辑。不过在现在,我们也无须自己编写一个PSR-4自动加载器了,因为我们可以使用依赖管理器Composer自动生成PSR-4自动加载器。