旧 PHP 与新 PHP

多年来,PHP 很可能已经帮助你成为一名更加严谨的开发人员。如果说在 PHP 诞生的最初几十年里,它允许你按照自己的意愿编写代码,而没有任何限制,这带来了(非常)少有的好处,那么事后看来,它之所以流行,主要是它提供了一个机会,让开发人员有尽可能多的方法来编写代码(这很少会带来卓越的结果)。我们现在知道,这可能会带来无穷无尽、难以调试的错误。幸运的是,过去几年语言的发展已经修复了许多错误,使我们的应用程序受益匪浅。

严格输入

首先,让我们来看看从 7.4 版开始的最新 PHP 版本中应该使用的最重要的东西之一—​属性的严格类型化。

曾几何时,你可以将任何数据传递给任何变量,也可以随心所欲地对变量进行转换,但却没有真正的本地方法来防止这种情况的发生—​将数组变量转换为字符串,将字符串转换为整数,等等。这可能会非常令人困惑,也可能是许多问题的根源。例如,如果将一个字符串乘以一个整数,会发生什么?结果完全出乎意料。在 Python 中,这种类型的运算是允许的,但却得到了很好的控制。如果你的 PHP 代码依赖于弱类型的能力,那么你的代码架构可能有问题,你必须重新检查需要弱类型的部分。

PHP 现在允许在某些情况下对变量进行严格类型化。从 PHP 8.1 开始,如果变量不是类属性或方法参数,就不能键入。尽管如此,还是应该键入类的所有属性和方法参数—​减少混乱,提高严谨性。你可能需要重新考虑代码的某些部分,但你将获得更简洁、更易懂的代码。运行时也不会因为意外的类型转换而出现意外。如果确实需要向方法传递任何类型的数据,仍然可以使用混合关键字,它告诉 PHP 这个变量可以是任何类型的数据,或者方法可以返回任何类型的数据。当然,如果可以的话,你必须避免使用这个关键字,而且只能在非常精确的情况下使用(例如接口方法定义,接口的实现可以返回多种类型的数据)。

错误报告

现在,PHP 8 默认显示弃用和更严格的错误。PHP 早期版本的错误报告级别较低。有了这一改动,你就能更容易地看到需要注意的地方,比如说弃用。例如,当你需要进行 PHP 版本升级时,你就会感谢这一更改。如果你能在出现弃用时及时修复,升级到另一个版本的 PHP 就会变得轻而易举。此外,几乎总是会有一条因弃用而产生的信息,告诉你如何准确地修复它。尽早解决这些错误,尤其是弃用问题,绝对是一个明智之举,而且还能让你采用清洁代码的思维方式。

属性

发明源代码中的注释是为了让人们更好地理解代码中棘手的部分。这意味着,如果我们去掉源代码中的所有注释,它应该也能完美运行,因为编译器和解释器不应该考虑注释。这就是源代码注释被发明的主要原因。

随后,注释应运而生。在注释部分引入了逻辑和机制。别误会,注释非常实用。你可以在需要的地方、需要的时候获得元素的所有信息和元数据。但仔细想想,这多少有些反常。请记住我们在前几章中说过的话:如果你的代码写得干净利落,那么你就很有可能永远不需要写一行注释,或者最多只需要写几行注释(即使是最好的干净利落的编码员,也无法避免写一些棘手的代码部分)。

从 8.0 版开始,属性就成为 PHP 语言的一部分。简单地说,属性的作用与注释相同:为不同的元素(包括类、属性和方法)添加元数据。不同的是,属性使用的是另一种语法,而不是注释所使用的类型。除了具有更好的可读性,注释还将回归其最初的用途:提供信息。在一个实例中,你可以立即区分元数据(用属性描述)和注释,从而更好地理解你正在处理的代码部分。

让我们来看看属性是什么样的:

<?php

namespace App\Controller;

class ExampleController
{
    public function home(#[CurrentUser] User $user)
    {
        // ...
    }
}
php

很明显,当前登录的用户可能会被注入 $user 变量中。代码看起来很清晰,我们也掌握了所有必要的信息,一目了然。如果我们需要在 home() 方法上方的注释部分添加信息,我们还有一个完美的空白空间。现在你可以清楚地看到属性是如何帮助你变得更加严谨的—​移除所有注释块,并在添加新注释块之前三思而后行。

从版本 8.0 开始,PHP 的最新版本中显然还有很多新东西。下面是一个不完整的列表:

  • 联合类型

  • 匹配语法

  • 命名参数

  • 枚举

  • JIT 编译器

  • Fibers

  • 数字分隔符

让我们在下一节中看看其中的一些。