点击上方关注Lemon黄,么么哒!
名人之声
实现明天理想的唯一障碍是今天的疑虑。
来源/https://www.startutorial.com/articles/view/modern-php-developer-psr
翻译/Lemon黄
在推荐PSR(PHP Standards Recommendation,PHP标准推荐)之前,编写PHP代码是没有一个真正统一的标准。例如,对于编码风格,有些人更喜欢Zend框架的编码标准,有些人喜欢PEAR的编码标准,还有一些人选择创建自己的命名约定和编码风格。
2009年,代表各种流行php项目的一群人聚集在一起,形成了一个称为FIG(Framework Interoperability Group)的组织。FIG的目的是让项目代表谈论他们的项目之间的共性并找到合作的方法。
在这篇文章中,有六个被接受的PSRs:其中两个是关于自动加载的,其中两个与PHP编码风格有关,剩下的是关于接口的。
在这一章中,我们将简要讨论每个PSR。本章的目的是向您介绍PSRs的思想。对于每一个的进一步细节,提供相应的链接。
1 PSR-0, PSR-4
PSR-0,和PSR-4这两个是关于自动加载的标准。自动加载,是PHP中包含一个类的基本方式,有了自动加载就不必在PHP中写那些杂乱无章的include/require语句。
让我们来看看自动加载的历史。这将使我们更加的直观了解到自动加载是如何参与进PHP中来。
在php语言中,我们必须确保在使用类定义之前加载它。通常,我们会在自己的类文件中创建php类,以便更好地组织。然后,我们将在调用它们的文件中加载require或include语句。如下示例代码:
include 'manager.php';$manager = new Manager();
假设有数十个外部类要在一个文件中使用,并且都需要在源文件的开头编写一行require/include语句。这将多么难看,并且用include语句的重复行扰乱了我们的代码库。
从php 5开始,引入了一个新的魔术函数来解决这个问题:
void __autoload ( string $class);
__autoload()函数本质上是一个辅助函数,做的就是处理我们使用的包含语句。我们可以在代码中的任何地方定义这个函数,当调用未定义的类时,php将自动使用这个函数加载类的文件。这是在php因错误而失败之前加载类定义的最后一次机会。
function __autoload($class){ $filename = 'classes/' . $class . '.php'; if (file_exists($filename)) { include_once($filename); }}$manager = new Manager();
因为只允许一个autoloader函数,__autoload很快就过时了。意思就是,由于autoload是php引擎将调用的唯一一个magic,我们需要在任何需要自动加载功能的地方定义这个特殊的magic函数。理论上,这将包括一个实际的面向对象代码库中的每个文件。
PHP5.1.2是用另一个自动加载函数(spl_autoload_register)来加载的,以应对__autoLoad的限制。spl_autoload_register是__autoLoad的替代品,它提供了更大的灵活性。它通过在自动加载队列中注册php用户登录函数来工作。它有效地创建了一个自动加载函数队列,并按定义它们的顺序遍历每个函数。这意味着我们可以有多个自动加载函数,不再需要在每个源文件中创建自动加载函数。
每个项目都开始使用自动加载是一个非常好的主意。不可避免的是,由于缺乏统一的标准,每个人都创建了自己的autoloader版本。显然,php迫切需要一个autoloader的标准,这就是PSR-0的诞生。
今天,自动加载器的标准有了很大的发展。然而PSR-0也因为一些限制因素而被官方废除,比如它对Composer的不友好。
现在最新能被接受的自动加载器标准是PSR-4。你应该遵循PSR-4标准来创建我们想要的自动加载器。有关PSR-4的详细介绍,请参阅其官方页面(http://www.php-fig.org/psr/psr-4/)。
2 PSR-1, PSR-2
PSR-1和PSR-2的标准是关于PHP编码的标准。PSR-1侧重于基础,而PSR-2扩展了PSR-1并提供了更全面的编码风格指南。
PSR-1列出了一组用于命名约定和文件结构的简单规则。它的主要目的是确保共享php代码之间具有高水平的技术可相互操作性。在一个包含不同软件包的项目中,如果每个软件包使用不同的编码标准(这正是PSR-1的设计初衷)可能会造成混乱。
PSR-1简介:
- 文件只能使用"<?php " 和"<?=" 标签。
- 文件只能使用无Bom的UTF-8编码格式的PHP代码
- 文件应声明符号(类、函数、常量等)或导致SID效果(例如生成输出、更改.ini设置等),但不应同时声明这两者。
- 命名空间和类必须遵循PSR-0。
- 类名必须用首字母大写驼峰式声明
- 类常量必须使用下划线分隔符以大写形式声明。
- 方法名必须用首字母小写驼峰式声明。
在PSR-1的基础上,PSR-2提供了更全面的指导,如基础的代码缩进等更详细的规则。它还涵盖了编码风格的各个方面,从命名约定到名称空间、类、属性、方法、控制结构和闭包。从PSR-2中都可以找到您需要的任何规范。为了实现可互操作性,我们非常鼓励您根据此标准调整您的代码。
3 PSR-3, PSR-7
在自动加载和编码标准之后,我们最终可以将PSR与php代码关联起来。这就需要通过PSR-3和PSR-7。PSR-3包含日志接口,PSR-7包含http消息接口的接口。
PSR-3:
php迫切需要PSR-3之前的日志接口标准。日志记录在开发中是常见的需求,所以每个项目都构建了自己的日志记录版本。如果没有标准,使用第三方日志的唯一方法就是在它周围编写一个包装器,这样它就可以使用我们现有的代码库。这不仅是一个痛苦的过程,而且感觉是错误的,因为毕竟他们都在做同样的工作:日志记录。我们应该要去调换他们。
PSR-3为日志库提供了通用接口。只要它们实现了PSR-3日志接口,理论上它们应该可以与任何其他PSR-3日志记录库互换。
让我们在一个具体的例子中看看PSR-3日志器接口如何提高代码的可重用性。
假设我们在下面编写了一个简单的用户身份验证类。用户成功登录后,它会将审核消息附加到日志文件中。它使用我们的自定义日志类,该类公开一个方法addMessage()。
class User{ private $logger; public function __construct($logger){ $this->logger = $logger; } public function login($username, $password){ if ($this->validUsernameAndPassword($username, $password)) { $this->logger->addMessage('login'); } } private function validUsernameAndPassword($username, $password){ // ... ... }}
我们的自定义日志类按照依赖注入原则注入到用户类中,这似乎使我们的用户可重用。我们可以简单地通过构造函数切换到其他日志类。但是如果我们仔细观察,我们就无法做到这一点,用户类仍然与我们的自定义日志类高度耦合,它知道自定义方法addMessage()。如果我们在代码中使用另一个第三方日志类,它将不起作用,因为它们没有名为addMessage的方法。
我们可以修改代码,使用PSR-3日志接口来替代。根据依赖倒置原理(SOLID),我们应该依赖抽象而不是具体化。PSR-3记录器接口为我们的案例提供了一个完美的抽象。
class User{ private $logger; public function __construct(PsrLogLoggerInterface $logger){ $this->logger = $logger; } public function login($username, $password){ if ($this->validUsernameAndPassword($username, $password)) { $this->logger->info('login'); } } private function validUsernameAndPassword($username, $password){ // ... ... }}
spl_autoload_register是自动加载的替代品,它提供了更大的灵活性。spl_autoload_register是自动加载的替代品,它提供了更大的灵活性。spl_autoload_register是自动加载的替代品,它提供了更大的灵活性。spl_autoload_register是自动加载的替代品,它提供了更大的灵活性。通过更改几行代码,我们已经用PsrLogLoggerInterface 替换了自定义日志类。现在我们的代码是高度可重用的。我们可以使用、切换或更改任何符合PSR-3日志接口的第三方日志库。
PSR-7:
http消息对于web应用程序是必不可少的。用户执行的每个操作都是http请求和http响应的组合。PSR-7是最新认可的标准。它提供了关于http消息及其组成元素的抽象。它将对实现http消息细节的项目产生巨大的影响,因为http是一个相当复杂的主题,而且大多数供应商都有自己的实现,因此供应商要适应PSR-7需要进行大量的重构。
作为http消息的用户,由于PSR-7,我们现在可以普遍地处理http消息。与PSR-3类似,PSR-7使我们的开发更容易构建可重用的代码库。
4 PSR规范
我们已经简要地总结了每个PSR规范,现在您应该了解每个PSR规范的用途。
当你需要每个PSR的详细规范时,你应该参考以下官方页面:
- PSR-1: http://www.php-fig.org/psr/psr-1/
- PSR-2: http://www.php-fig.org/psr/psr-2/
- PSR-3: http://www.php-fig.org/psr/psr-3/
- PSR-4: http://www.php-fig.org/psr/psr-4/
- PSR-7: http://www.php-fig.org/psr/psr-7/
等风
也等你
Lemon黄