新功能

PHP 核心

类型化属性

类属性现在支持类型声明。

<?php
class User {
public
int $id;
public
string $name;
}
?>
上面的例子将强制执行 $user->id 只能被赋值为 int 值,而 $user->name 只能被赋值为 string 值。

箭头函数

箭头函数 提供了一种简写语法来定义具有隐式按值作用域绑定的函数。

<?php
$factor
= 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>

有限的返回类型协变和参数类型逆变

以下代码现在可以工作

<?php
class A {}
class
B extends A {}

class
Producer {
public function
method(): A {}
}
class
ChildProducer extends Producer {
public function
method(): B {}
}
?>
完整的方差支持仅在使用自动加载时可用。在单个文件中,只允许非循环类型引用,因为所有类都需要在被引用之前可用。

空合并赋值运算符

<?php
$array
['key'] ??= computeDefault();
// 大致等同于
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>

在数组中解包

<?php
$parts
= ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>

数字字面量分隔符

数字字面量可以在数字之间包含下划线。

<?php
6.674_083e-11
; // float
299_792_458; // decimal
0xCAFE_F00D; // hexadecimal
0b0101_1111; // binary
?>

弱引用

弱引用 允许程序员保留对对象的引用,但不会阻止该对象被销毁。

允许来自 __toString() 的异常

现在允许从 __toString() 中抛出异常。以前,这会导致致命错误。现有的字符串转换中的可恢复致命错误已转换为 Error 异常。

CURL

CURLFile 现在除了支持普通文件名外,还支持流包装器,前提是扩展已针对 libcurl >= 7.56.0 构建。

过滤器

FILTER_VALIDATE_FLOAT 过滤器现在支持 min_rangemax_range 选项,与 FILTER_VALIDATE_INT 的语义相同。

FFI

FFI 是一个新的扩展,它提供了一种简单的方法来调用原生函数、访问原生变量以及创建/访问在 C 库中定义的数据结构。

GD

添加了 IMG_FILTER_SCATTER 图像过滤器,用于将散点过滤器应用于图像。

哈希

添加了使用 Castagnoli 多项式的 crc32c 哈希。此 CRC32 变体被存储系统使用,例如 iSCSI、SCTP、Btrfs 和 ext4。

多字节字符串

添加了 mb_str_split() 函数,它提供与 str_split() 相同的功能,但操作的是码点而不是字节。

OPcache

已添加对 预加载代码 的支持。

正则表达式(Perl 兼容)

preg_replace_callback()preg_replace_callback_array() 函数现在接受一个额外的 flags 参数,支持 PREG_OFFSET_CAPTUREPREG_UNMATCHED_AS_NULL 标志。这会影响传递给回调函数的匹配数组的格式。

PDO

现在可以在 PDO DSN 中为 mysql、mssql、sybase、dblib、firebird 和 oci 驱动程序指定用户名和密码。以前,这仅由 pgsql 驱动程序支持。如果在构造函数和 DSN 中都指定了用户名/密码,则构造函数优先。

现在可以转义 SQL 查询中的问号,以避免将其解释为参数占位符。写 ?? 允许向数据库发送单个问号,例如使用 PostgreSQL JSON 键存在 (?) 运算符。

PDO_OCI

PDOStatement::getColumnMeta() 现在可用。

PDO_SQLite

PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) 允许检查语句是否为只读,即它是否不会修改数据库。

PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true) 允许在 PDO::errorInfo()PDOStatement::errorInfo() 中使用 SQLite3 扩展结果代码。

SQLite3

添加了 SQLite3::lastExtendedErrorCode() 来获取最后一个扩展结果代码。

添加了 SQLite3::enableExtendedResultCodes($enable = true),这将使 SQLite3::lastErrorCode() 返回扩展结果代码。

标准

带有标签名称数组的 strip_tags()

strip_tags() 现在也接受允许的标签数组:而不是 strip_tags($str, '<a><p>'),您现在可以写 strip_tags($str, ['a', 'p'])

自定义对象序列化

添加了一种用于自定义对象序列化的新机制,它使用两种新的魔术方法:__serialize__unserialize

<?php
// 返回包含对象所有必要状态的数组。
public function __serialize(): array;

// 从给定的数据数组中恢复对象状态。
public function __unserialize(array $data): void;
?>
新的序列化机制取代了Serializable 接口,该接口将在未来被弃用。

无参数的数组合并函数

array_merge()array_merge_recursive() 现在可以不带任何参数调用,在这种情况下,它们将返回一个空数组。 这在与扩展运算符结合使用时很有用,例如 array_merge(...$arrays)

proc_open() 函数

proc_open() 现在接受一个数组而不是一个字符串作为命令。 在这种情况下,进程将直接打开(不通过 shell),PHP 将处理任何必要的参数转义。

<?php
proc_open
(['php', '-r', 'echo "Hello World\n";'], $descriptors, $pipes);
?>

proc_open() 现在支持 redirectnull 描述符。

<?php
// 类似于 shell 中的 2>&1
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);
// 类似于 shell 中的 2>/dev/null 或 2>nul
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
?>

没有 libargon 的 argon2i(d)

password_hash() 现在在 PHP 构建时没有 libargon 的情况下,具有来自 sodium 扩展的 argon2i 和 argon2id 实现。

添加注释

用户贡献注释 2 条注释

98
Rain
4 年前
需要注意的是,类型化属性在内部从未被初始化为默认的 null。 除非你自行将它们初始化为 null。 这就是为什么如果你在初始化之前尝试访问它们,你总是会遇到此错误的原因。

**类型化属性 foo::$bar 必须在初始化之前不可访问**

<?php
class User
{
public
$id;
public
string $name; // 类型化属性 (未初始化)
public ?string $age = null; // 类型化属性 (已初始化)
}

$user = new User;
var_dump(is_null($user->id)); // bool(true)
var_dump(is_null($user->name)); // PHP 致命错误:类型化属性 User::$name 必须在初始化之前不可访问
var_dump(is_null($user->age));// bool(true)
?>

另外值得注意的是,无法将类型为对象的属性初始化为除 null 以外的任何值。 因为属性的求值发生在编译时,而对象实例化发生在运行时。 最后一点,由于其上下文相关的行为,不可调用类型不受支持。
7
wow-apps.pro
4 年前
<?php

// 如何获取属性类型? 例如用于测试:

class Foo
{
private
int $num;
private
bool $isPositive;
private
$notes;
}

$reflection = new \ReflectionClass(Foo::class);
$classProperties = $reflection->getProperties(\ReflectionProperty::IS_PRIVATE);
foreach (
$classProperties as $classProperty) {
var_dump((string) $classProperty->getType());
}

/**
* 结果:
* "int"
* "bool"
* ""
*/
To Top