class Status
{
const DRAFT = 'draft';
const PUBLISHED = 'published';
const ARCHIVED = 'archived';
}
function acceptStatus(string $status) {...}
enum Status
{
case Draft;
case Published;
case Archived;
}
function acceptStatus(Status $status) {...}
class BlogData
{
private Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
public function getStatus(): Status
{
return $this->status;
}
}
class BlogData
{
public readonly Status $status;
public function __construct(Status $status)
{
$this->status = $status;
}
}
只读属性在初始化后(即为其赋值后)不能更改。
它们是模拟值对象和数据传输对象的绝佳方式。
$foo = [$this, 'foo'];
$fn = Closure::fromCallable('strlen');
$foo = $this->foo(...);
$fn = strlen(...);
现在可以获取任何函数的引用——这称为一等可调用语法。
class Service
{
private Logger $logger;
public function __construct(
?Logger $logger = null,
) {
$this->logger = $logger ?? new NullLogger();
}
}
class Service
{
private Logger $logger;
public function __construct(
Logger $logger = new NullLogger(),
) {
$this->logger = $logger;
}
}
对象现在可以作为默认参数值、静态变量和全局常量使用,以及在属性参数中使用。
这实际上使得使用**嵌套属性**成为可能。
class User
{
/**
* @Assert\All({
* @Assert\NotNull,
* @Assert\Length(min=5)
* })
*/
public string $name = '';
}
class User
{
#[\Assert\All(
new \Assert\NotNull,
new \Assert\Length(min: 5))
]
public string $name = '';
}
function count_and_iterate(Iterator $value) {
if (!($value instanceof Countable)) {
throw new TypeError('value must be Countable');
}
foreach ($value as $val) {
echo $val;
}
count($value);
}
function count_and_iterate(Iterator&Countable $value) {
foreach ($value as $val) {
echo $val;
}
count($value);
}
当一个值需要同时满足多个类型约束时,使用交集类型。
目前无法混合使用交集类型和联合类型,例如 A&B|C
。
function redirect(string $uri) {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage() {
redirect('/login');
echo 'Hello'; // <- 死代码
}
function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage(): never {
redirect('/login');
echo 'Hello'; // <- 静态分析检测到死代码
}
用 `never` 类型声明的函数或方法表示它不会返回值,并且会抛出异常或使用 `die()`、`exit()`、`trigger_error()` 或类似的方法结束脚本的执行。
class Foo
{
public const XX = "foo";
}
class Bar extends Foo
{
public const XX = "bar"; // 无错误
}
class Foo
{
final public const XX = "foo";
}
class Bar extends Foo
{
public const XX = "bar"; // 致命错误
}
可以声明最终类常量,这样子类就不能重写它们。
016 === 16; // false,因为`016`是八进制的`14`,容易混淆
016 === 14; // true
0o16 === 16; // false — 使用显式表示法不会混淆
0o16 === 14; // true
现在可以使用显式的0o
前缀编写八进制数。
$httpClient->request('https://example.com/')
->then(function (Response $response) {
return $response->getBody()->buffer();
})
->then(function (string $responseBody) {
print json_decode($responseBody)['code'];
});
$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];
纤程是实现轻量级协作并发原语。它们是一种创建代码块的方法,这些代码块可以像生成器一样暂停和恢复,但可以在堆栈中的任何位置进行。纤程本身不会神奇地提供并发性,仍然需要一个事件循环。但是,它们允许阻塞和非阻塞实现共享相同的 API。
纤程允许摆脱以前使用Promise::then()
或基于生成器的协程看到的样板代码。库通常会在纤程周围构建更高级的抽象,因此无需直接与它们交互。
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = array_merge(['a' => 0], $arrayA, $arrayB);
// ['a' => 1, 'b' => 2]
$arrayA = ['a' => 1];
$arrayB = ['b' => 2];
$result = ['a' => 0, ...$arrayA, ...$arrayB];
// ['a' => 1, 'b' => 2]
PHP 之前支持通过扩展运算符在数组内解包,但前提是数组必须具有整数键。现在也可以解包具有字符串键的数组。
#[ReturnTypeWillChange]
属性。fsync
和fdatasync
函数。array_is_list
函数。Serializable
接口已弃用。$GLOBALS
变量限制。file_info
资源迁移到现有的 finfo 对象。IMAP\Connection
类对象。FTP\Connection
类对象。GdFont
类对象。LDAP\Connection
、LDAP\Result
和LDAP\ResultEntry
类对象。PgSql\Connection
、PgSql\Result
和PgSql\Lob
类对象。PSpell\Dictionary
、PSpell\Config
类对象。