新特性

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, [1234]);
// $nums = array(10, 20, 30, 40);
?>

有限返回类型协变与参数类型逆变

以下代码现在可以正常执行:

<?php
class {}
class 
extends {}

class 
Producer {
    public function 
method(): {}
}
class 
ChildProducer extends Producer {
    public function 
method(): {}
}
?>
只有在使用自动加载的情况下,才会有完整的差异支持。在一个文件内,只有非循环类型引用是可能的,因为在引用之前,所有的类都需要可用。

空合并运算符赋值

<?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

如果扩展是使用 libcurl >= 7.56.0 构建的,CURLFile 现在除了支持普通文件名之外还支持流封装协议。

Filter

FILTER_VALIDATE_FLOAT 过滤器现在支持 min_rangemax_range 选项,其含义跟 FILTER_VALIDATE_INT 相同。

FFI

FFI 是新扩展,提供了简单的方式去 C 库中调用原生函数、访问原生变量和创建和访问定义的数据结构。

GD

添加 IMG_FILTER_SCATTER 图片过滤器以将分散过滤器(scatter filter)应用于图片。

Hash

Added crc32c hash using Castagnoli's polynomial. This CRC32 variant is used by storage systems, such as iSCSI, SCTP, Btrfs and ext4.

多字节字符串

新增 mb_str_split() 函数,提供了跟 str_split() 相同的行为,但是在代码点上操作,而不是字节。

OPcache

新增 缓存预加载 特性。

正则表达式(兼容 Perl)

preg_replace_callback()preg_replace_callback_array() 函数现在接受附加的 flags 参数,支持 PREG_OFFSET_CAPTUREPREG_UNMATCHED_AS_NULL flag。这会影响传递给回调函数的匹配数组的格式。

PDO

现在可以将用户名和密码指定为 mysql、mssql、sybase、dblib、firebird 和 oci 驱动程序的 PDO DSN 的一部分。之前仅支持 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

Added SQLite3::lastExtendedErrorCode() to fetch the last extended result code.

Added SQLite3::enableExtendedResultCodes($enable = true), which will make SQLite3::lastErrorCode() return extended result codes.

标准

带标签数组的 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
// Like 2>&1 on the shell
proc_open($cmd, [=> ['pipe''w'], => ['redirect'1]], $pipes);
// Like 2>/dev/null or 2>nul on the shell
proc_open($cmd, [=> ['pipe''w'], => ['null']], $pipes);
?>

argon2i(d) without libargon

password_hash() now has the argon2i and argon2id implementations from the sodium extension when PHP is built without libargon.

add a note add a note

User Contributed Notes 2 notes

up
69
Rain
2 years ago
It should be noted that typed properties internally are never initialized to a default null. Unless of course you initialize them to null yourself. That's why you will always going to encounter this error if you try to access them before initialization.

**Typed property foo::$bar must not be accessed before initialization**

<?php
class User
{
    public
$id;
    public
string $name; // Typed property (Uninitialized)
   
public ?string $age = null; //  Typed property (Initialized)
}

$user = new User;
var_dump(is_null($user->id)); // bool(true)
var_dump(is_null($user->name)); // PHP Fatal error: Typed property User::$name must not be accessed before initialization
var_dump(is_null($user->age));// bool(true)
?>

Another thing worth noting is that it's not possible to initialize a property of type object to anything other than null.  Since the evaluation of properties happens at compile-time and object instantiation happens at runtime. One last thing, callable type is not supported due to its context-dependent behavior.
up
6
wow-apps.pro
2 years ago
<?php

// How to get property type? For example for testing:

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());
}

/**
* Result:
* "int"
* "bool"
* ""
*/
To Top