PHP 8.4 正式版发布,一文快速预览新功能
PHP 8.4 在 11 月 21 号就发布了,它包含了许多新功能,对于 WordPress 用户来说,了解 PHP 新版的功能也是一个简单必要的工作,并且 8.4 版是 PHP 在 2024 年的年度的一个主要的版本更新,所以我们就简单快速过一遍 PHP 8.4 的新功能。😄
属性挂钩
对象属性现在可以其 get
和 set
操作中关联相关的附加逻辑。根据用法,这可能会也可能不会使属性变为虚拟属性,即该属性根本没有实际的存储值。
<?php
class Person
{
// “虚拟”属性,可能无法明确设置。
public string $fullName {
get => $this->firstName . ' ' . $this->lastName;
}
// 所有的写入操作都会经过这个挂钩,结果就是写入的内容。
// 读取访问正常。
public string $firstName {
set => ucfirst(strtolower($value));
}
// 所有的写入操作都会经过这个挂钩,它必须写入支持值本身。
// 读取访问正常。
public string $lastName {
set {
if (strlen($value) < 2) {
throw new \InvalidArgumentException('Too short');
}
$this->lastName = $value;
}
}
}
$p = new Person();
$p->firstName = 'peter';
print $p->firstName; // 打印“Peter”
$p->lastName = 'Peterson';
print $p->fullName; // 打印“Peter Peterson”
不对称属性可见性
现在可以将对象属性的 set
可见性和 get
可见性分开控制。
<?php
class Example
{
// 第一个可见性修饰符控制 get 可见性,第二个修饰符控制 set 可见性。
// The get-visibility must not be narrower than set-visibility.
public protected(set) string $name;
public function __construct(string $name)
{
$this->name = $name;
}
}
惰性对象
现在可以创建对象,将初始化延迟到访问时。库和框架可以利用这些惰性对象来延迟获取初始化所需的数据或依赖项。
<?php
class Example
{
public function __construct(private int $data)
{
}
// ...
}
$initializer = static function (Example $ghost): void {
// 获取数据或者依赖项
$data = ...;
// 初始化
$ghost->__construct($data);
};
$reflector = new ReflectionClass(Example::class);
$object = $reflector->newLazyGhost($initializer);
#[\Deprecated]
属性
新的 #[\Deprecated]
属性使 PHP 的现有弃用机制可用于用户定义的函数、方法和类常量。
class PhpVersion
{
#[\Deprecated(
message: "use PhpVersion::getVersion() instead",
since: "8.4",
)]
public function getPhpVersion(): string
{
return $this->getVersion();
}
public function getVersion(): string
{
return '8.4';
}
}
$phpVersion = new PhpVersion();
// Deprecated: Method PhpVersion::getPhpVersion() is deprecated since 8.4, use PhpVersion::getVersion() instead
echo $phpVersion->getPhpVersion();
新的 ext-dom 功能和 HTML5 支持
新的 DOM API 包括符合标准的支持,用于解析 HTML5 文档,修复了 DOM 功能行为中的几个长期存在的规范性错误,并添加了几个函数,使处理文档更加方便。
新的 DOM API 可以在 Dom
命名空间中使用。使用新的 DOM API 可以使用 Dom\HTMLDocument
和 Dom\XMLDocument
类创建文档。
$dom = Dom\HTMLDocument::createFromString(
<<<HTML
<main>
<article>PHP 8.4 is a feature-rich release!</article>
<article class="featured">PHP 8.4 adds new DOM classes that are spec-compliant, keeping the old ones for compatibility.</article>
</main>
HTML,
LIBXML_NOERROR,
);
$node = $dom->querySelector('main > article:last-child');
var_dump($node->classList->contains("featured")); // bool(true)
BCMath 的对象 API
新的 BcMath\Number
对象使在处理任意精度数字时可以使用面向对象的方式和标准的数学运算符。
这些对象是不可变的,并实现了 Stringable
接口,因此可以在字符串上下文中使用,如 echo $num
。
use BcMath\Number;
$num1 = new Number('0.12345');
$num2 = new Number('2');
$result = $num1 + $num2;
echo $result; // '2.12345'
var_dump($num1 > $num2); // false
新的 array_*()
函数
新增函数 array_find()
、array_find_key()
、array_any()
和 array_all()
$animal = array_find(
['dog', 'cat', 'cow', 'duck', 'goose'],
static fn (string $value): bool => str_starts_with($value, 'c'),
);
var_dump($animal); // string(3) "cat"
PDO 驱动程序特定子类
新的 Pdo\Dblib
、Pdo\Firebird
、Pdo\MySql
、Pdo\Odbc
、Pdo\Pgsql
和 Pdo\Sqlite
的子类可用。
$connection = PDO::connect(
'sqlite:foo.db',
$username,
$password,
); // object(Pdo\Sqlite)
$connection->createFunction(
'prepend_php',
static fn ($string) => "PHP {$string}",
); // Does not exist on a mismatching driver.
$connection->query('SELECT prepend_php(version) FROM php');
new MyClass()->method()
不需要括号
现在可以在不使用括号包裹 new
表达式的情况下访问新实例化对象的属性和方法。
$connection = PDO::connect(
'sqlite:foo.db',
$username,
$password,
); // object(Pdo\Sqlite)
$connection->createFunction(
'prepend_php',
static fn ($string) => "PHP {$string}",
); // Does not exist on a mismatching driver.
$connection->query('SELECT prepend_php(version) FROM php');
新的类、接口和函数
新的 延迟对象。
基于 IR 框架的新 JIT 实现。
新增 request_parse_body() 函数。
新增 bcceil()、bcdivmod()、bcfloor() 和 bcround() 函数。
新增 RoundingMode 枚举用于 round(),包括 4 个新的舍入模式 TowardsZero、AwayFromZero、NegativeInfinity 和 PositiveInfinity。
新增 DateTime::createFromTimestamp()、DateTime::getMicrosecond()、DateTime::setMicrosecond()、DateTimeImmutable::createFromTimestamp()、DateTimeImmutable::getMicrosecond() 和 DateTimeImmutable::setMicrosecond() 方法。
新增 mb_trim()、mb_ltrim()、mb_rtrim()、mb_ucfirst() 和 mb_lcfirst() 函数。
新增 pcntl_getcpu()、pcntl_getcpuaffinity()、pcntl_getqos_class()、pcntl_setns() 和 pcntl_waitid() 函数。
新增 ReflectionClassConstant::isDeprecated()、ReflectionGenerator::isClosed() 和 ReflectionProperty::isDynamic() 方法。
新增 http_get_last_response_headers()、http_clear_last_response_headers() 和 fpow() 函数。
新增 XMLReader::fromStream()、XMLReader::fromUri()、XMLReader::fromString()、XMLWriter::toStream()、XMLWriter::toUri() 和 XMLWriter::toMemory() 方法。
新增 grapheme_str_split() 函数。
弃用和向后不兼容
IMAP、OCI8、PDO_OCI 和 pspell 扩展已从 PHP 中分离并移至 PECL。
隐式可空参数类型现已弃用。
使用 _ 作为类名现已弃用。
将零的负数次幂现已弃用。
向 round() 传递无效模式将抛出 ValueError。
来自扩展 date、intl、pdo、reflection、spl、sqlite、xmlreader 的类常量现在是有类型的。
GMP 类现已是 final 类。
已删除 MYSQLI_SET_CHARSET_DIR、MYSQLI_STMT_ATTR_PREFETCH_ROWS、MYSQLI_CURSOR_TYPE_FOR_UPDATE、MYSQLI_CURSOR_TYPE_SCROLLABLE 和 MYSQLI_TYPE_INTERVAL 常量。
已弃用 mysqli_ping()、mysqli_kill()、mysqli_refresh() 函数,mysqli::ping()、mysqli::kill()、mysqli::refresh() 方法,以及 MYSQLI_REFRESH_* 常量。
stream_bucket_make_writeable() 和 stream_bucket_new() 现在返回 StreamBucket 实例而不是 stdClass。
exit() 行为变更。
E_STRICT 常量已弃用。
所以你打算升级吗?我打算先把 WPJAM 所有插件的最低版本的要求从 7.4 先升级到 8.0 了,不过现在我已经开始修复一些插件在 PHP 8 版本的兼容问题了。