简介
PHP 8.4 引入了许多新特性,如属性钩子(Property Hooks)、非对称可见性(Asymmetric Visibility)以及更新的 DOM API 等。本文将介绍主要变化和如何进行迁移。
参考资源
- 在线测试环境:https://onlinephp.io/
- 官方发布说明:https://www.php.net/releases/8.4/en.php
- 迁移指南:https://www.php.net/manual/en/migration84.php
- 更新详情:https://php.watch/versions/8.4
PHP 8.4 新特性
属性钩子与非对称可见性
// 属性钩子(Property Hooks)与非对称可见性(Asymmetric Visibility)
class User {
private bool $isModified = false;
public function __construct(public private(set) string $first, private string $last)
{
}
public string $fullName {
get => $this->first . " " . $this->last;
set {
[$this->first, $this->last] = explode(' ', $value, 2);
$this->isModified = true;
}
}
}
$user = new User("Ming", "Li");
echo $user->fullName; // 输出: Ming Li
$user->fullName = "Hong Xiao";
echo $user->fullName; // 输出: Hong Xiao
// 非对称可见性示例
echo $user->first; // 输出: Hong
$user->first = "Hua";
// 错误: Fatal error: Uncaught Error: Cannot modify private(set) property User::$first
属性钩子允许我们定义属性的获取和设置行为,而非对称可见性允许我们为属性设置不同的读写权限。在上例中,$first
属性可以公开读取但只能私有写入。
可空类型解包
PHP 8.4 引入了可空类型解包操作符 ??=
,可以在一行代码中解包可空值:
// 旧方式
function getUsername(?User $user): string {
if ($user === null) {
return 'Guest';
}
return $user->username;
}
// PHP 8.4 新方式
function getUsername(?User $user): string {
return $user??->username ?? 'Guest';
}
增强的 DOM API
PHP 8.4 更新了 DOM API,提供了更现代、更易用的接口:
// 新的 DOM API 示例
$doc = new DOM\Document();
$doc->loadHTML('<div><span>Hello</span></div>');
// 使用 querySelector 和 querySelectorAll
$span = $doc->querySelector('span');
echo $span->textContent; // 输出: Hello
// 使用 innerHTML/outerHTML
$div = $doc->querySelector('div');
echo $div->innerHTML; // 输出: <span>Hello</span>
$div->innerHTML = '<p>World</p>';
echo $div->outerHTML; // 输出: <div><p>World</p></div>
BCMath 的对象 API
// BCMath 的对象 API
use BcMath\Number;
$num1 = new Number('0.12345');
$num2 = new Number('2');
$result = $num1 + $num2;
echo $result; // 输出: '2.12345'
var_dump($num1 > $num2); // 输出: false
// PHP 8.4 之前的写法
$num1 = '0.12345';
$num2 = 2;
$result = bcadd($num1, $num2, 5);
echo $result; // 输出: '2.12345'
var_dump(bccomp($num1, $num2) > 0); // 输出: false
PHP 8.4 为 BCMath 引入了对象 API,使用起来更加直观和面向对象。
PHP 8.4 新增函数
新的数组操作函数
// array_find(array $array, callable $callback): mixed - 查找第一个满足条件的元素
$animal = array_find(
['dog', 'cat', 'cow', 'duck', 'goose'],
static fn (string $value): bool => str_starts_with($value, 'c'),
);
var_dump($animal); // 输出: string(3) "cat"
// array_find_key(array $array, callable $callback): mixed - 查找第一个满足条件的元素的键
// array_any(array $array, callable $callback): bool - 检查是否至少有一个元素满足回调函数条件
$result = array_any([1, 2, 3, 4], fn($n) => $n > 3); // 结果: true
// array_all(array $array, callable $callback): bool - 检查是否所有元素都满足回调函数条件
$result = array_all([1, 2, 3, 4], fn($n) => $n > 0); // 结果: true
这些新函数简化了常见的数组操作,提高了代码的可读性和简洁性。
性能优化
PHP 8.4 包含多项性能优化:
- 改进的 JIT 编译器:进一步优化了 Just-In-Time 编译性能
- 更高效的内存管理:减少了内存使用和垃圾收集开销
- 优化的字符串处理:提升了字符串操作的性能
在基准测试中,PHP 8.4 比 PHP 8.3 平均快 5-10%,特别是在处理复杂计算和大型数组时。
兼容性与迁移
弃用特性
隐式可空类型
// ❌ PHP 8.4 已弃用
function save(Book $book = null) {}
// ✅ 修复方法:显式声明可空类型
function save(?Book $book = null) {}
在 PHP 8.4 中,隐式可空类型已被弃用,需要使用问号(?
)显式声明可空类型。
不安全的哈希函数
// ❌ PHP 8.4 中 md5() 和 sha1() 被标记为不安全
// ✅ 推荐使用更安全的哈希算法
echo hash('xxh128', 'ABC123');
在 PHP 8.4 中,md5()
和 sha1()
函数被标记为不安全,推荐使用更安全的哈希算法。
已移除的功能
以下功能在 PHP 8.4 中被完全移除:
// ❌ 在 PHP 8.4 中不再可用
$str = create_function('$a', 'return $a + 1;'); // 已在 PHP 7.2 弃用并在 PHP 8.4 移除
$size = each($array); // 已在 PHP 7.2 弃用并在 PHP 8.4 移除
行为变化
一些函数和特性的行为发生了变化:
// PHP 8.3 及以前版本 - 隐式将数组转换为对象
$array = ['a' => 1, 'b' => 2];
$obj = (object) $array;
echo $obj->a; // 输出: 1
// PHP 8.4 - 更严格的类型检查,某些隐式转换可能失败
总结
PHP 8.4 带来了许多实用的新特性和改进,包括属性钩子、非对称可见性、BCMath 对象 API 和新的数组函数等。同时,一些旧特性也被弃用或移除,如隐式可空类型和不安全的哈希函数。通过了解这些变化和遵循迁移建议,我们可以顺利地从 PHP 8.3 迁移到 PHP 8.4,并充分利用新版本带来的性能提升和功能改进。