PHP 作为最流行的后端脚本语言之一,自诞生以来便不断演进。从早期的松散特性到现代的强类型、高性能,每一次版本迭代都带来了显著的改进。本文将详细回顾 PHP 7.0 以后,各个主要版本(7.x 和 8.x 系列)引入的新特性、性能提升和废弃功能,帮助开发者理解 PHP 的发展轨迹并更好地进行技术选型和代码迁移。

核心思想:PHP 的演进主线是:提高性能、增强类型系统、简化语法、引入现代编程范式和清理历史遗留问题。


一、PHP 7.0 (2015年) - 性能飞跃的起点

PHP 7.0 是一个里程碑式的版本,其最大的亮点是引入了全新的 Zend Engine (Zend Engine 3.0,代号 PHPNG),带来了惊人的性能提升。

1.1 核心特性与性能提升

  • Zend Engine 3.0 (PHPNG):这是 7.0 最大的亮点。与 PHP 5.6 相比,PHP 7.0 在实际应用中实现了 2 倍甚至更高的性能提升,大幅降低了内存消耗。这是通过重写 Zend Engine 的核心,优化了数据结构、Opcodes 处理和垃圾回收机制实现的。
  • 抽象语法树 (Abstract Syntax Tree, AST):PHP 7.0 在内部引入了 AST,这为后续的性能优化、静态分析和编译器改进奠定了基础。
  • 标量类型声明 (Scalar Type Declarations)
    • 允许对函数参数和返回值声明标量类型(int, float, string, bool)。
    • 支持两种模式:
      • 强制模式 (Coercive Mode):默认模式,PHP 会尝试将传入的值转换为声明的类型(例如,"123" 会被转换为 123)。
      • 严格模式 (Strict Mode):通过 declare(strict_types=1); 开启,不允许隐式类型转换,类型不匹配会抛出 TypeError
  • 返回值类型声明 (Return Type Declarations)
    • 与标量类型声明类似,允许声明函数返回值的类型。
  • Null 合并运算符 (Null Coalescing Operator) ??
    • 简化了检查变量是否存在并取值的逻辑。
    • $foo = $bar ?? 'default'; 等价于 $foo = isset($bar) ? $bar : 'default';
  • 太空船操作符 (Spaceship Operator) <=>
    • 用于比较两个表达式,当 $a < $b 时返回 -1,当 $a == $b 时返回 0,当 $a > $b 时返回 1。
    • 主要用于排序回调函数。
  • 匿名类 (Anonymous Classes)
    • 允许直接在代码中定义和实例化没有名称的类,简化了只使用一次的简单对象的创建。
  • Group Use Declarations
    • 允许在 use 语句中对来自同一命名空间的类、函数或常量进行分组,例如 use Some\Namespace\{ClassA, ClassB, ClassC as C};
  • Closure::call()
    • 允许临时绑定一个闭包到另一个对象并调用它,无需修改对象的可见性。
  • Generator Return Expressions
    • 允许生成器函数使用 return 语句返回最终值。

1.2 废弃与移除

  • 废弃了旧的 PHP 4 风格构造函数(与类名相同的函数)。
  • 移除了 ASP 和 Script tag。
  • 移除了 mysql 扩展(推荐使用 mysqli 或 PDO)。
  • 移除了各种旧的、不推荐使用的功能。

二、PHP 7.1 (2016年) - 持续完善类型系统

PHP 7.1 在 7.0 的基础上,继续完善了类型系统,并引入了一些方便的语法糖。

2.1 核心特性

  • 可为空类型 (Nullable Types)
    • 在类型声明前加上 ?,表示该参数或返回值可以是指定类型,也可以是 null
    • 例如:function foo(?string $bar): ?int {...}
  • Void 返回类型 (Void Return Type)
    • 函数不返回任何值时,可以声明返回类型为 void
    • 例如:function logMessage(string $message): void {...}
  • 类常量可见性 (Class Constant Visibility)
    • 允许为类常量定义 public, protected, private 可见性。
  • 多捕获异常 (Multi-catch Exception Handling)
    • catch 语句中可以使用 | 捕获多个异常类型。
    • 例如:catch (FirstException | SecondException $e) {...}
  • Iterable 伪类型 (Iterable Pseudo-type)
    • 新的伪类型 iterable,可用于参数和返回值类型声明,表示该值是数组或 Traversable 接口的实现。
  • List Syntax With Keys
    • 允许在 list() 结构中指定键,例如 list('a' => $a, 'b' => $b) = $array;
  • HTTP/2 Server Push 支持
    • curl 扩展支持 HTTP/2 Server Push (需要 cURL 7.46.0+)。

2.2 废弃与移除

  • 废弃了 ext/mcrypt 扩展,推荐使用 ext/libsodium 或 OpenSSL。
  • 废弃了 __FILE__ 魔术常量作为目录使用,推荐使用 __DIR__

三、PHP 7.2 (2017年) - 强化安全与现代功能

PHP 7.2 主要围绕安全性和一些现代功能的引入。

3.1 核心特性

  • 新的 object 类型声明
    • 引入了新的伪类型 object,允许将 object 作为函数参数和返回值类型声明。
    • 例如:function process(object $data): object {...}
  • Libsodium 扩展
    • libsodium 密码学库作为核心扩展集成到 PHP 中,提供了现代、安全的加密和哈希功能。
    • 这是 PHP 首次将加密库内置到核心中。
  • 参数类型反协变和返回值类型协变
    • 子类方法的参数类型可以与父类方法参数类型不同,只要它更宽泛(反协变)。
    • 子类方法的返回值类型可以与父类方法返回值类型不同,只要它更具体(协变)。
  • 允许在 trait 中使用抽象方法
    • trait 中可以包含抽象方法,要求使用 trait 的类实现这些抽象方法。
  • Trailing Comma in List Syntax
    • 允许在 list() 语法中使用逗号作为最后一个元素的后缀,方便多行定义。
    • 例如:list($a, $b,) = [1, 2];

3.2 废弃与移除

  • 废弃了 __autoload() 函数,推荐使用 spl_autoload_register()
  • 废弃了 each() 函数。
  • 废弃了 create_function() 函数。

四、PHP 7.3 (2018年) - 语法糖与性能微调

PHP 7.3 带来了更多语法糖和性能微调。

4.1 核心特性

  • 灵活的 Heredoc 和 Nowdoc 语法
    • 允许在 Heredoc/Nowdoc 标记中不缩进,并允许结束标记后跟分号。
    • 例如:
      1
      2
      3
      $str = <<<EOT
      Hello world!
      EOT; // 结束标记可以不缩进
  • List Reference Assignment (列表引用赋值)
    • 允许在 list() 赋值时使用引用。
    • 例如:list(&$a, &$b) = $arr;
  • is_countable() 函数
    • 用于检查变量是否可以被 count() 函数计数(即是否是数组或实现了 Countable 接口的对象),避免了 count() 在不可计数类型上抛出警告。
  • array_key_first()array_key_last() 函数
    • 获取数组的第一个或最后一个键。
  • JSON_THROW_ON_ERROR 常量
    • json_decode()json_encode() 函数在遇到错误时不再返回 null,而是抛出 JsonException
  • PCRE2 支持
    • 正则表达式引擎更新为 PCRE2,带来了更好的性能和更多的特性。

4.2 废弃与移除

  • 废弃了不区分大小写的常量定义。
  • 废弃了 image2wbmp() 函数。

五、PHP 7.4 (2019年) - 质的飞跃,为 PHP 8 铺路

PHP 7.4 是 PHP 7.x 系列的最后一个主要版本,引入了大量重要特性,为 PHP 8.0 的到来做了很好的铺垫。

5.1 核心特性

  • 类型化属性 (Typed Properties)
    • 允许为类的属性声明类型,例如 public string $name;
    • 这是 PHP 类型系统的一大进步,使得代码更加健壮和易于维护。
  • 箭头函数 (Arrow Functions) fn()
    • 提供了一种更简洁的匿名函数写法,用于单行表达式。
    • 自动从父作用域捕获变量(按值),无需 use 关键字。
    • 例如:$result = array_map(fn($x) => $x * $x, $numbers);
  • Foregin Function Interface (FFI)
    • 允许从 PHP 代码中直接调用 C 语言函数和访问 C 语言数据结构,而无需编写 PHP 扩展。
    • 为 PHP 与底层系统交互提供了新的强大能力。
  • 预加载 (Preloading)
    • 在服务器启动时,将一系列 PHP 文件加载到 Opcache 内存中,并在随后的请求中直接使用,避免了每次请求的编译和加载开销。
    • 显著提升了框架和大型应用的性能。
  • 空合并赋值运算符 (Null Coalescing Assignment Operator) ??=
    • 简化了检查变量是否为空并赋值的逻辑。
    • $array['key'] ??= computeDefault(); 等价于 if (!isset($array['key'])) { $array['key'] = computeDefault(); }
  • Spread Operator in Array Expression (数组展开运算符)
    • 可以在数组字面量中使用 ... 运算符展开数组。
    • 例如:$merged = [...$array1, ...$array2];
  • Casts for custom classes
    • 允许对自定义类进行类型转换(不常用)。
  • 密码学改进
    • password_hash() 默认算法更新为 ARGON2ID13

5.2 废弃与移除

  • 废弃了左结合的三元运算符。
  • 废弃了不带参数调用 get_parent_class()
  • 废弃了 implode() 不符合参数顺序的用法。

六、PHP 8.0 (2020年) - 现代化的重大飞跃

PHP 8.0 是自 7.0 以来最重要的版本更新,引入了 JIT 编译器、联合类型等大量激动人心的新特性,并进一步提升了性能。

6.1 核心特性与性能提升

  • JIT (Just In Time) 编译器
    • PHP 8.0 引入了两个 JIT 引擎:Tracing JIT 和 Function JIT。
    • 它将部分热点代码在运行时直接编译成机器码执行,绕过 Zend VM。
    • 影响:对于 CPU 密集型任务(如数学计算、图像处理),性能有显著提升;对于典型的 Web 应用(I/O 密集型),性能提升不如 7.0 显著,但仍有积极作用。
  • 联合类型 (Union Types) |
    • 允许函数参数、返回值或属性接受多种不同类型。
    • 例如:public function foo(int|float $number): string|null {...}
  • 属性 (Attributes / Annotations)
    • 一种将元数据添加到类、方法、属性、函数和参数的结构化方式。
    • 取代了 PHPDoc 注释中用于框架配置的非标准约定,使得框架和工具能够以标准方式读取元数据。
    • 例如:
      1
      2
      #[Route("/api/users", methods: ["GET"])]
      public function getUsers() { /* ... */ }
  • 构造器属性提升 (Constructor Property Promotion)
    • 一种更简洁的语法,允许在构造函数的参数列表中直接定义并初始化类属性。
    • 例如:class User { public function __construct(public string $name, public int $age) {} }
  • match 表达式
    • 作为 switch 语句的更安全、更简洁的替代品。
    • match 是一个表达式,会返回一个值。
    • 支持多条件匹配、严格类型比较 ( === ),并且必须处理所有可能的匹配(或抛出 UnhandledMatchError)。
    • 例如:
      1
      2
      3
      4
      5
      $result = match ($status) {
      0, 1 => 'Pending',
      2 => 'Approved',
      default => 'Unknown',
      };
  • nullsafe 运算符 ?->
    • 类似 JavaScript 的可选链(Optional Chaining),当链中任何一个元素为 null 时,整个表达式立即返回 null 而不会抛出 TypeError
    • 例如:$country = $user?->getAddress()?->getCountry();
  • 命名参数 (Named Arguments)
    • 允许在调用函数时通过参数名来传递参数,无需严格按照参数顺序。
    • 提高了代码可读性,并且可以跳过可选参数。
    • 例如:array_fill(start_index: 0, num: 100, value: 'foo');
  • 更严格的类型检查
    • 对内部函数和运算符进行了更严格的类型检查,减少了隐式类型转换的意外行为。
  • 字符串到数字的比较优化
    • 现在进行字符串和数字比较时,PHP 会优先将数字转换为字符串进行比较,而不是字符串转数字,减少了意外行为。
  • str_contains(), str_starts_with(), str_ends_with() 函数
    • 提供了更直观、更高效的字符串查找函数。
  • Weak Maps (弱映射)
    • 键不会阻止垃圾回收,当键对象被垃圾回收后,其对应的映射条目也会自动移除。
    • 适用于缓存等场景。

6.2 废弃与移除

  • 移除了 create_function()
  • 移除了 @ 错误抑制符对 E_ERRORE_PARSE 的作用。
  • 废弃了 @ 错误抑制符在一些特定上下文中的使用。
  • 严格了数字字符串的转换行为。

七、PHP 8.1 (2021年) - 枚举、只读属性和 Fiber

PHP 8.1 持续引入现代语言特性,并关注并发和性能。

7.1 核心特性

  • 枚举 (Enums)
    • 引入了原生的枚举类型,允许定义一组命名常量,并且可以与类型系统集成。
    • 支持纯枚举 (Pure Enums) 和支持值的枚举 (Backed Enums)。
    • 例如:
      1
      2
      3
      4
      5
      6
      enum Status: string {
      case Pending = 'pending';
      case Approved = 'approved';
      case Rejected = 'rejected';
      }
      function process(Status $status) { /* ... */ }
  • 只读属性 (Readonly Properties)
    • 允许将类属性声明为 readonly,一旦初始化(在构造函数中),就不能再被修改。
    • 增强了对象的不变性。
    • 例如:class User { public readonly string $name; public function __construct(string $name) { $this->name = $name; } }
  • Fibers (协程)
    • 引入了用户空间的协程支持,允许在 PHP 中实现非阻塞的并发编程。
    • Fiber 允许代码在执行过程中暂停和恢复,而无需使用生成器或回调地狱。
    • 这是构建异步 PHP 应用(如 ReactPHP, Amphp)的基础。
  • 交叉类型 (Intersection Types) &
    • 允许参数、返回值或属性必须同时满足多个接口或类。
    • 例如:function process(Logger&Cache $service) {...}
  • 新的 never 返回类型
    • 表示函数永远不会返回(要么抛出异常,要么终止脚本)。
    • 对于一些工具函数和框架内部的函数很有用。
  • array_is_list() 函数
    • 检查一个数组是否是“列表” (即所有键都是连续的从 0 开始的整数,且没有间隙)。
  • fsync()fdatasync()
    • 文件系统同步函数。
  • First-class Callable Syntax (一等调用语法)
    • 允许将任何可调用对象转换为 Closure 对象,而无需显式使用 Closure::fromCallable()
    • 例如:$closure = my_function(...);$closure = $object->method(...);

7.2 废弃与移除

  • 废弃了 floatint 的隐式转换 (strict_types=1 下会报错)。
  • 废弃了在一些场景下 new 关键字在非对象上的使用。
  • 一些内部函数的参数类型变严格。

八、PHP 8.2 (2022年) - 只读类、Disjunctive Normal Form (DNF) 类型

PHP 8.2 继续在类型系统和安全方面发力。

8.1 核心特性

  • 只读类 (Readonly Classes)
    • 允许将整个类声明为 readonly,这意味着该类的所有属性都必须是只读的。
    • 如果类包含 readonly 属性,则其所有属性必须是 readonly 的。
    • 进一步增强了数据不变性。
    • 例如:readonly class User { public string $name; public int $age; }
  • 弃用动态属性 (Deprecate Dynamic Properties)
    • 在 PHP 8.2 中,尝试在类外部定义非声明属性会发出弃用警告。
    • 在 PHP 9.0 中将被完全移除。
    • 目标是提高代码的健壮性和可维护性,防止意外的属性创建。
    • 如果需要动态属性,应明确使用 #[AllowDynamicProperties] 属性或继承 stdClass
  • Disjunctive Normal Form (DNF) 类型
    • 允许组合联合类型和交叉类型,以表达更复杂的类型约束。
    • 例如:(A&B)|D 表示类型必须是 A 和 B 的交叉类型,或者类型 D。
    • ((A&B)|C)|D
  • 新的随机数扩展 (Random Extension)
    • 提供了一个更健壮、更灵活、更可控的随机数生成器 API。
    • 取代了旧的 mt_rand() 等函数,解决了其内部状态管理的限制。
  • 常量中的敏感参数检测 (Sensitive Parameter Redaction)
    • 通过 #[SensitiveParameter] 属性,可以在堆栈跟踪中自动隐藏敏感参数(如密码),防止在生产环境日志中泄露。
    • 例如:function login(string $username, #[SensitiveParameter] string $password) { /* ... */ }
  • true, false, null 作为独立类型
    • 允许在类型声明中使用 true, false, null 作为独立类型,使得类型系统更加精确。
    • 例如:function checkStatus(): true { return true; }

8.2 废弃与移除

  • 弃用动态属性(见上文)。
  • mb_convert_encoding() 等多字节字符串函数中,一些不常用的编码别名被移除。

九、PHP 8.3 (2023年) - 持续改进

PHP 8.3 是一个维护和改进版本,包含了进一步的优化和少量新特性。

9.1 核心特性

  • #[Override] 属性
    • 一个静态分析属性,用于明确标记一个方法是重写父类或接口的方法。
    • 如果标记了 #[Override] 的方法在父类/接口中不存在同名方法,PHP 将会抛出编译时错误,防止因方法名拼写错误导致的 bug。
    • 例如:
      1
      2
      3
      4
      5
      6
      7
      class ParentClass {
      public function foo(): void {}
      }
      class ChildClass extends ParentClass {
      #[Override] // 明确表示这是对 ParentClass::foo() 的重写
      public function foo(): void {}
      }
  • 深度克隆只读属性 (Deep Cloning of Readonly Properties)
    • __clone() 魔术方法中,允许对 readonly 属性进行深度克隆(即重新赋值)。
    • 解决了只读属性在克隆时的一些限制,使得 readonly 类在需要进行复杂克隆操作时更加实用。
  • 类常量类型 (Class Constant Type Declarations)
    • 允许为类常量声明类型,进一步增强了类型系统的完整性。
    • 例如:const string NAME = 'App';
  • json_validate() 函数
    • 一个更高效的函数,用于检查一个字符串是否是有效的 JSON,而无需将其解析为 PHP 数组或对象。
    • 对于只需要验证 JSON 有效性而不需要其内容的场景非常有用。
  • 新的 gc_status() 函数
    • 提供更详细的垃圾回收器状态信息。
  • 随机数生成器改进
    • Randomizer 类增加了新的方法和功能。
  • CURL 支持 CURLINFO_EFFECTIVE_METHODCURLINFO_TOTAL_TIME_CONNNECT

9.2 废弃与移除

  • 废弃了 mt_rand()mt_srand() 函数,推荐使用新的 Randomizer 类。

十、总结与展望

PHP 在 7.0 以后取得了巨大的进步,从一个被戏称为“最好用的模板语言”发展成为一个高性能、现代化、类型安全的后端语言。

  • 性能方面:PHP 7.0 的 Zend Engine 3.0 和 PHP 8.0 的 JIT 编译器带来了革命性的性能提升,使 PHP 在 Web 应用领域更具竞争力。
  • 类型系统方面:从标量类型声明、返回值类型声明、可为空类型到类型化属性、联合类型、交叉类型、只读属性和枚举,PHP 的类型系统日益完善,使得代码更加健壮、可维护,并为静态分析工具提供了更多便利。
  • 语法与功能方面:箭头函数、Null 合并运算符、match 表达式、命名参数、属性等语法糖和新功能大大提升了开发效率和代码的可读性。
  • 安全与最佳实践:内置 libsodium、弃用动态属性、敏感参数隐藏等都体现了 PHP 社区对安全性和代码质量的重视。

随着 PHP 版本的不断更新,我们可以预见它将继续在性能、类型安全、并发能力和开发者体验方面持续进步,为 Web 开发带来更多可能性。建议开发者始终关注最新版本,并尽可能升级到最新的稳定版本,以利用其带来的性能和功能优势。