Loading

php 8.0及以上版本都引入了哪些特性?

PHP 8 及其后续版本(8.1, 8.2, 8.3)引入了一系列强大的新特性,极大地提升了语言的表现力、类型安全性和性能。下面我将为你详细梳理每个版本的主要新特性。


PHP 8.0 - 一次重大的里程碑式更新

PHP 8.0 是继 PHP 7.0 之后又一个重大版本,引入了 JIT 编译器联合类型注解等革命性特性。

1. JIT 编译器

  • 描述Just-In-Time 编译器在运行时将 PHP 操作码编译为机器码并直接执行,绕过 Zend VM,从而在 CPU 密集型任务中带来显著的性能提升。

  • 用途:主要用于数学计算、大型数组处理、游戏开发等场景。对于典型的 Web 应用(如 Laravel、WordPress),提升可能不那么明显。

  • 配置:在 php.ini 中通过 opcache.jit 选项控制。

2. 联合类型

  • 描述:允许一个参数、属性或返回值声明为多种类型之一。

  • 语法:使用 TypeA|TypeB 的语法。

  • 示例

    class User {
        public function __construct(
            private int|string $id, // $id 可以是整数或字符串
            private string|Address $address // $address 可以是字符串或 Address 对象
        ) {}
    
        public function findById(int|string $id): User|false {
            // 返回 User 对象或 false
        }
    }

3. 注解

  • 描述:PHP 原生支持了注解(在其他语言中常称为 Decorators),用于为方法属性等添加元数据。它们由 #[Attr] 语法定义,并可通过 Reflection API 读取。

  • 示例

    #[Attribute]
    class Route {
        public function __construct(public string $path, public string $method) {}
    }
    
    #[Route("/users", "GET")]
    class UserController {
        #[Route("/users/{id}", "GET")]
        public function show(#[MapInt] int $id) { }
    }

    框架(如 Symfony、Laravel)广泛使用它来定义路由、依赖注入等。

4. 匹配表达式

  • 描述match 是 switch 语句的更强大、更安全的替代品。它是一个表达式,有返回值,不需要 break,并且支持严格比较(===)。

  • 示例

    // PHP 7 - switch
    switch ($statusCode) {
        case 200:
            $message = 'OK';
            break;
        case 404:
            $message = 'Not Found';
            break;
        default:
            $message = 'Unknown';
    }
    
    // PHP 8 - match
    $message = match ($statusCode) {
        200 => 'OK',
        404 => 'Not Found',
        default => 'Unknown',
    };

5. 构造器属性提升

  • 描述:一种更简洁的语法,允许在类的构造器参数直接定义属性

  • 示例

    // PHP 7
    class User {
        private string $name;
        private int $age;
        public function __construct(string $name, int $age) {
            $this->name = $name;
            $this->age = $age;
        }
    }
    
    // PHP 8
    class User {
        public function __construct(
            private string $name,
            private int $age
        ) {}
    }

6. Nullsafe 运算符

  • 描述?-> 运算符在链式调用中,如果某个环节 null,则整个表达式的结果为 null,而不会抛出错误

  • 示例

    $country = $user?->getProfile()?->getAddress()?->getCountry();
    // 如果 $user 为 null,或者在链式调用中任何一步返回 null,则 $country 为 null。

7. 字符串与数字的比较更合理

  • 描述:当比较数字和字符串时,PHP 8 会将字符串转换为数字进行比较,而不是将数字转换为字符串。这解决了之前一些反直觉的比较结果(如 0 == "abc" 在 PHP 7 中为 true,在 8.0 中为 false)。

8. 新增和移除的内置函数/类

  • 新增str_contains()str_starts_with()str_ends_with() 等常用字符串函数。

  • 移除:一些不推荐使用的功能,如 create_function()


PHP 8.1 - 枚举、只读属性与 Fibers

1. 枚举

  • 描述:PHP 终于有了原生枚举支持!枚举是一种定义一组命名常量的特殊类。

  • 类型

    • 纯枚举:不关联标量值。

      enum Status {
          case PENDING;
          case ACTIVE;
          case EXPIRED;
      }
    • 回退枚举:关联一个标量值(字符串或整数)。

      enum Status: string {
          case PENDING = 'pending';
          case ACTIVE = 'active';
          case EXPIRED = 'expired';
      }
  • 方法:枚举可以有方法接口

    enum Status {
        case PENDING;
        case ACTIVE;
        public function color(): string {
            return match($this) {
                Status::PENDING => 'gray',
                Status::ACTIVE => 'green',
            };
        }
    }

2. 只读属性

  • 描述readonly 修饰符确保一个属性在初始化后(通常在构造器中)就不能再被修改

  • 示例

    class BlogPost {
        public function __construct(
            public readonly string $title,
            public readonly DateTime $createdAt
        ) {}
    }
    
    $post = new BlogPost('PHP 8.1', new DateTime());
    // $post->title = "New Title"; // 错误!不能修改只读属性

3. Fibers

  • 描述:Fibers 为 PHP 带来了轻量级的用户态的协程,用于管理异步编程并发。它们本身不提供异步事件循环,而是为像 ReactPHPAmphp 这样的框架提供了底层构建块。

  • 用途:简化异步代码的编写,避免“回调地狱”。

4. 新的数组解包语法

  • 描述:使用 ... 操作符可以对数组字面量进行解包,包括带有字符串键的数组。

  • 示例

    $arrayA = ['a' => 1];
    $arrayB = ['b' => 2];
    $result = ['c' => 3, ...$arrayA, ...$arrayB];
    // $result 是 ['c' => 3, 'a' => 1, 'b' => 2]

5. 交集类型

  • 描述:与联合类型相反,它要求一个值同时满足多个类型约束。使用 TypeA&TypeB 语法。

  • 示例

    function process(Countable&Iterator $item) {
        // $item 必须同时实现 Countable 和 Iterator 接口
    }

6. never 返回类型

  • 描述:表示一个函数或方法永远不会返回值,即一定会抛出异常或终止脚本(例如 exit()die())。

  • 示例

    function redirect(string $url): never {
        header('Location: ' . $url);
        exit();
    }

PHP 8.2 - 只读类与独立类型

1. 只读类

  • 描述:将整个类声明为 readonly,意味着该类的所有实例属性都是只读的。

  • 示例

    readonly class User {
        public string $name;
        public int $age;
        public function __construct(string $name, int $age) {
            $this->name = $name;
            $this->age = $age;
        }
    }
    // 等价于在 PHP 8.1 中给每个属性添加 `readonly` 修饰符。

2. 独立类型

  • 描述nulltrue 和 false 现在可以作为独立类型使用。这在联合类型中特别有用,可以精确表示返回状态。

  • 示例

    function findUser(int $id): User|null {}
    function isTrue(): true {} // 必须返回 true
    function validate(mixed $input): bool {
        return $input === 'valid' ? true : false;
        // 如果尝试返回非布尔值,会报错
    }

3. 析取范式类型

  • 描述:允许在联合类型中使用交集类型,使得类型声明更加灵活。

  • 示例

    function foo((A&B)|null $thing) {
        // $thing 可以是 (A和B的交集) 或者是 null
    }

4. 常量表达式中的枚举

  • 描述:现在可以在常量表达式中使用枚举变量。

  • 示例

    enum Status { 
        case PENDING; 
    }
    class Foo {
        const BAR = Status::PENDING; // PHP 8.2 之前不允许
    }

5. 新的 Random 扩展

  • 描述:提供了一个面向对象的 API 来生成随机数,替代旧的 rand() 和 mt_rand()

  • 示例

    use Random\Randomizer;
    $randomizer = new Randomizer();
    $value = $randomizer->getInt(1, 100); // 生成一个 1 到 100 之间的整数

PHP 8.3 - 渐进式增强

1. 类型化类常量

  • 描述类常量现在可以声明类型,提高了代码的清晰度类型安全性

  • 示例

    class Foo {
        const string BAR = 'baz'; // 常量 BAR 必须是字符串类型
        public const int STATUS_CODE = 200;
    }
    interface I {
        const string TEST = 'test'; // 接口常量也可以类型化
    }

2. 动态获取类常量和枚举成员

  • 描述:新增 constant() 和 enum_case() 函数,用于动态地获取常量和枚举成员。

  • 示例

    class Foo { 
        const BAR = 'test'; 
    }
    
    $name = 'BAR';
    $constName = 'FOO';
    
    var_dump(constant(Foo::class . "::" . $name)); // 输出:string(4) "test"
    
    enum Size { 
        case SMALL; 
    }
    
    var_dump(enum_case(Size::class, 'SMALL')); // 输出:enum(Size::SMALL)

3. 深拷贝 clone

  • 描述:新增 __clone 魔术方法可以通过 readonly 修饰符来阻止在克隆时修改属性,实现了深拷贝的语义。

  • 示例

    class PHP {
        public function __clone(): void {
            $this->version = clone $this->version; // 确保克隆嵌套对象
        }
    }

4. 新增 json_validate() 函数

  • 描述:在不分配内存的情况下快速验证一个字符串是否是有效的 JSON,比 json_decode() 更高效,尤其对于大 JSON 字符串。

  • 示例

    if (json_validate($maybeJson)) {
        // 是有效的 JSON
    }

5. 更直观的 Randomizer 添加

  • 描述:为 Randomizer 类添加了新方法,如 getBytesFromString(),用于从给定字符串中随机获取字节。

  • 示例

    $randomizer = new Random\Randomizer();
    $alphabet = 'abcdefghijklmnopqrstuvwxyz';
    $randomString = $randomizer->getBytesFromString($alphabet, 10); // 生成长度为10的随机字符串

总结

从 PHP 8.0 到 8.3,PHP 语言正在朝着更现代化、更类型安全、性能更高的方向飞速发展。

  • PHP 8.0 是基石,带来了 JIT、联合类型、注解等核心特性。

  • PHP 8.1 填补了重要空白,引入了枚举和只读属性。

  • PHP 8.2 和 8.3 则是在此基础上进行优化和增强,提供了更精细的类型控制和更好的开发者体验。

对于新项目,强烈建议直接从 PHP 8.2 或 8.3 开始。对于现有项目,也应制定计划升级到 PHP 8.x 系列,以享受其带来的性能和安全优势。在升级时,请务必参考官方升级指南,注意不兼容的变更。

posted @ 2025-11-06 10:26  Carver大脸猫  阅读(2)  评论(0)    收藏  举报