/ PHP  PHP8.4  属性钩子  不对称可见性  数组函数  HTML5解析器  新特性  性能优化 

PHP 8.4 新特性完全指南:属性钩子、不对称可见性与数组新函数


封面

PHP 8.4 重磅发布:值得升级的理由

PHP 8.4 于 2024 年 11 月 21 日正式发布,这是 PHP 8.x 系列中改动最为深远的一个版本。从语言层面到标准库,从性能到安全性,PHP 8.4 带来了一系列令开发者兴奋的新特性。无论你是做 Laravel、Symfony 还是原生 PHP 开发,了解这些新特性都能让你的代码更简洁、更具表达力。

本文将逐一介绍 PHP 8.4 的核心新特性,并配合真实代码示例,帮你快速上手。

属性钩子(Property Hooks):告别 Getter/Setter 样板代码

这是 PHP 8.4 最受期待的特性之一。以前我们写数据类时,往往需要大量的 getXxx()setXxx() 方法来封装属性,代码冗余且繁琐。属性钩子让你可以直接在属性声明处定义 getset 逻辑。

<?php

class User
{
    public string $name {
        get => strtoupper($this->name);
        set(string $value) {
            if (strlen($value) < 2) {
                throw new \ValueError('姓名不能少于2个字符');
            }
            $this->name = $value;
        }
    }

    public string $email {
        set(string $value) {
            $this->email = strtolower(trim($value));
        }
    }

    public function __construct(string $name, string $email)
    {
        $this->name  = $name;
        $this->email = $email;
    }
}

$user = new User('zhang san', 'ADMIN@Example.COM');
echo $user->name;  // 输出:ZHANG SAN
echo $user->email; // 输出:admin@example.com

属性钩子支持只定义 get(只读派生属性)或只定义 set(仅做写入校验),也可以同时定义两者。这让值对象(Value Object)的编写变得前所未有的优雅。

  • 支持在接口(interface)中声明带钩子的属性

  • 子类可以细化(narrow)父类的属性钩子

  • 与构造器属性提升(Constructor Promotion)完全兼容

  • 只有 get 钩子的属性自动变为虚拟只读属性

不对称可见性(Asymmetric Visibility):精细控制读写权限

PHP 8.4 引入了 public private(set) 这样的不对称可见性语法,允许属性的读取权限和写入权限独立配置。

<?php

class BankAccount
{
    public private(set) float $balance = 0.0;
    public readonly string $accountNumber;

    public function __construct(string $accountNumber)
    {
        $this->accountNumber = $accountNumber;
    }

    public function deposit(float $amount): void
    {
        if ($amount <= 0) {
            throw new \InvalidArgumentException('存款金额必须大于0');
        }
        $this->balance += $amount;
    }

    public function withdraw(float $amount): void
    {
        if ($amount > $this->balance) {
            throw new \RuntimeException('余额不足');
        }
        $this->balance -= $amount;
    }
}

$account = new BankAccount('ACC-001');
$account->deposit(1000);
echo $account->balance; // 外部可读:1000

// $account->balance = 9999; // 报错!外部不可写

不对称可见性支持以下组合:

  • public protected(set):公开读取,仅类及子类可写

  • public private(set):公开读取,仅类内部可写

  • protected private(set):受保护读取,仅类内部可写

这个特性完美替代了大量只读属性场景下的 readonly 局限,同时保留了内部修改的灵活性。

数组操作新函数:array_find、array_find_key、array_any、array_all

PHP 8.4 终于在标准库中补充了几个期待已久的数组函数,让数组处理更加语义化。

<?php

$users = [
    ['name' => '张三', 'age' => 25, 'vip' => true],
    ['name' => '李四', 'age' => 17, 'vip' => false],
    ['name' => '王五', 'age' => 30, 'vip' => true],
];

// array_find:找到第一个满足条件的元素
$firstVip = array_find($users, fn($u) => $u['vip'] === true);
// 结果:['name' => '张三', 'age' => 25, 'vip' => true]

// array_find_key:找到第一个满足条件的键
$minorKey = array_find_key($users, fn($u) => $u['age'] < 18);
// 结果:1

// array_any:是否存在至少一个满足条件的元素
$hasMinor = array_any($users, fn($u) => $u['age'] < 18);
// 结果:true

// array_all:是否所有元素都满足条件
$allVip = array_all($users, fn($u) => $u['vip'] === true);
// 结果:false

这些函数在 JavaScript 中早已是标配(findfindIndexsomeevery),PHP 8.4 终于补上了这块短板。与 array_filter + array_shift 的组合相比,新函数不仅语义更清晰,性能也更好(找到第一个匹配即停止遍历)。

全新 HTML5 解析器:Dom\HTMLDocument

PHP 8.4 内置了基于 Lexbor 引擎的 HTML5 标准解析器,通过全新的 Dom\HTMLDocument 类提供,彻底告别了旧版 DOMDocument 在解析现代 HTML 时的各种奇怪问题。

<?php

// 旧方式(PHP 8.3 及以前)
$oldDoc = new \DOMDocument();
@$oldDoc->loadHTML('<div><p>Hello</p></div>');

// 新方式(PHP 8.4)
$doc = \Dom\HTMLDocument::createFromString('
    <!DOCTYPE html>
    <html lang="zh">
    <body>
        <article class="post">
            <h1>PHP 8.4 新特性</h1>
            <p>精彩内容</p>
        </article>
    </body>
    </html>
');

// 支持 CSS 选择器查询
$heading = $doc->querySelector('article h1');
echo $heading->textContent; // PHP 8.4 新特性

$paragraphs = $doc->querySelectorAll('article p');
foreach ($paragraphs as $p) {
    echo $p->textContent . PHP_EOL;
}

新解析器的优势:

  • 完整支持 HTML5 标准,正确处理自闭合标签、模板标签等

  • 原生支持 querySelector / querySelectorAll CSS 选择器

  • 解析 UTF-8 内容不再乱码

  • 可通过 Dom\XMLDocument 处理 XML

  • 旧的 DOMDocument 类仍然保留,向后兼容

其他实用改进:链式方法调用、JIT 增强与弃用清理

除了上述重头特性,PHP 8.4 还带来了一系列细节改进:

new 表达式无需括号即可链式调用

<?php

// PHP 8.3:必须加括号
$result = (new MyBuilder())->setName('test')->build();

// PHP 8.4:直接链式调用,无需外层括号
$result = new MyBuilder()->setName('test')->build();

// 同样适用于静态方法
$conn = new PDO(dsn: 'sqlite::memory:');

命名参数(Named Arguments)增强

PHP 8.4 对内置函数的命名参数支持更为完善,许多之前无法使用命名参数的内置函数现在都支持了,使调用更具可读性。

JIT 编译器优化

PHP 8.4 对 JIT 编译器进行了重构,修复了多个内存问题,并在循环密集型计算场景下带来约 5-15% 的性能提升。启用方式与之前版本相同:

; php.ini
opcache.enable=1
opcache.jit_buffer_size=128M
opcache.jit=tracing

弃用与移除

  • 隐式的可空类型(?string 替代 string = null)现在发出弃用警告

  • E_STRICT 常量被弃用

  • 部分 IMAP、LDAP 扩展函数重命名,旧名称弃用

  • 移除了若干 PHP 8.1/8.2 中已弃用的功能

升级建议与兼容性

PHP 8.4 的升级路径相对平滑,与 PHP 8.3 的不兼容变更较少。以下是升级建议:

  • 检查弃用警告:先在 PHP 8.3 下开启 E_DEPRECATED,修复所有弃用警告后再升级

  • 扩展兼容性:检查第三方扩展是否已支持 PHP 8.4,特别是 PECL 扩展

  • 框架支持:Laravel 11+、Symfony 7+ 已完整支持 PHP 8.4

  • Docker 升级:直接替换基础镜像 FROM php:8.4-fpm 即可快速体验

  • 测试先行:建议先在 CI 环境跑完整测试套件,确认无问题后再部署生产

PHP 8.4 是一个真正意义上让 PHP 更现代化的版本,属性钩子和不对称可见性的引入,让 PHP 在面向对象编程的表达力上迈出了重要一步。建议所有 PHP 开发者尽早将项目升级到 8.4,享受这些新特性带来的开发体验提升。

发布评论

热门评论区: