PHP 8 中新特性以及重大调整

珠江路在线   2020年7月7日  【 转载 】 

PHP 8,PHP 的一个新的大版本,估计将于2020年12月3日公布,这 象征着将不会有 PHP 7.5 版本 。PHP8当前正处于十分活跃的开发阶段,所以在接下来的几个月里,状况可能会 产生很大的 变迁 。

在这篇文章中,我会维持一个最新的清单列表,列出估计会浮现的新 特点、性能 晋升和 打破性的 变迁 。因为 PHP 8 是一个新的大版本, 因而您的代码被 毁坏的可能性更高 。假如您始终 维持运行 PHP 的最新版本,那么 晋级 绝对来说就会轻松众多,因为在7. *版本中,大多数重大更改均已弃用 。

除重大更改外,PHP 8还带来了一些不错的新 性能, 比方说 JIT编译器, 联合类型, 属性,以及更多 。

新 特点

从新 特点开始,请记住 PHP8 仍处于 运动开发阶段, 因而此列表将随着 工夫的推移而增进 。

联合类型

考量到 PHP 动态语言类型的 特点,现在众多状况下,联合类型都是很有用的 。联合类型是两个或者多个类型的 集中, 示意 能够 使用其中任何一个类型 。

public function foo(Foo|Bar $input): int|float;

请 留神,联合类型中不包含 void,因为void 示意的 含意是“ 根本没有返回值” 。 另外, 能够 使用 |null 或者现有的 ? 示意法来 示意包含 nullable 的联合体 :

public function foo(Foo|null $foo): void;

public function bar(?Bar $bar): void;

JIT

JIT — just in time — 编译器 固然不总是在 Web 申请的上下文中,但是有望显着地 遍及性能 。当前还没有 实现任何精确的基准测试,但是 确定会到来 。

假如您想进一步了解JIT对PHP的作用, 能够阅读我写过的另一篇文章此处 。

属性

属性在 其余语言中通常被称为 注解 ,提供一种在无需解析文档块的状况下将元数据增加到类中的 步骤 。

快捷阅读一下,这里有一份来自 RFC 的属性示例:

use AppAttributesExampleAttribute;

<>

class Foo

{

<>

public const FOO = 'foo';

<>

public $x;

<>

public function foo(<> $bar) { }

}

<>

class ExampleAttribute

{

public $value;

public function __construct($value)

{

$this->value = $value;

}

}

假如您想 深刻了解属性如何工作以及如何构建自己的属性,您 能够在此博客上阅读有关 深刻属性的信息 。

新增 static 返回类型

只管已经 能够返回 self,但是 static 直到 PHP 8 才是有效的返回类型  。考量到 PHP 存在动态类型的性质,此 性能关于许多开发人员将十分有用 。

class Foo

{

public function test(): static

{

return new static();

}

}

新增 mixed 类型

有人可能将其称为必要的邪恶:mixed 类型让许多人觉得十分 混乱 。但是,有一个很好的论据 支撑去实现它: 缺乏类型在 PHP 中会招致众多状况:

  • 函数不返回任何内容或返回空值
  • 我们需求多 品种型的一 品种型
  • 我们需求的是PHP中不能进行类型 揭示的类型

因为上述缘由,增加 mixed 类型是一件很棒的事儿 。mixed 本身代表下列类型中的任一类型:

  • array
  • bool
  • callable
  • int
  • float
  • null
  • object
  • resource
  • string

请 留神,mixed 不只仅 能够用来作为返回类型,还 能够用作参数和属性类型 。

另外,还需求 留神,因为 mixed 类型已经包含了 null, 因而 mixed 类型不可为空 。下面的代码会触发致命 舛误:

// 致命 舛误:混合类型不能为空,null已经是混合类型的一 部分 。

function bar(): ?mixed {}

throw 抒发式

该RFC将throw从一个语句更改为一个 抒发式,这使得 能够在众多新地方抛出 异样:

$triggerError = fn () => throw new MyError();

$foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');

弱映射

基于在 PHP 7.4 中新增的 弱 引用 RFC,PHP 8 中新增了 WeakMaps(弱映射)的实现 。 WeakMaps(弱映射)在 维持对一些对象的 引用的同时,并不会组织这些对象被垃圾回收机制 解决  。

以ORM为例,它们通常实现 保留对实体类的 引用的缓存,从而 遍及实体类中间关联的性能 。 只有缓存中存在对这些实体类的 引用,那么这些类就 无奈被垃圾回收机制回收, 只管除了缓存中,已经没有别处再 引用这些实体类,它们依旧不会被垃圾 解决机制 解决 。

假如这个缓存层 使用了弱 引用和弱映射,那么 PHP 将会在这些实体类没有任何 其余 引用时,对其进行垃圾回收 。 尤其是关于 ORMs,它 能够治理一个 申请中的数百个(假如不是数千个)实体;弱映射 能够提供一种更好的、对资源更 友爱的 模式来 解决这些对象 。

下面是弱映射 根本的例子,摘抄自 RFC :

class Foo

{

private WeakMap $cache;

public function getSomethingWithCaching(object $obj): object

{

return $this->cache[$obj]

??= $this->computeSomethingExpensive($obj);

}

}

同意对对象 使用 ::class

一个很小但是很有用的新 特点:现在 能够在对象上 使用 :: class ,而 无须在对象上 使用 get_class() ,它的工作 模式跟 get_class() 雷同 。

$foo = new Foo();

var_dump($foo::class);

Non-capturing catches

在PHP 8 之前,无论何时你想要 拿获一个 异样,你都需求先将其存储到一个变量中, 无论这个变量你是不是会用到 。通过 Non-capturing catches 你 能够 忽略变量,所以替换下面的代码:

try {

// Something goes wrong

} catch (MySpecialException $exception) {

Log::error("Something went wrong");

}

你现在 能够这么做:

try {

// Something goes wrong

} catch (MySpecialException) {

Log::error("Something went wrong");

}

请 留神,必须始终指定类型,不同意将 catch 留空,假如你想要 拿获全部类型的 异样和 舛误,需求 使用 Throwable 作为 拿获类型 。

参数列表中的尾部逗号

当调用函数时已经 支撑尾部逗号,但是参数列表中 依然 缺乏跟随逗号 支撑 。现在PHP8中同意这样做,这 象征着您 能够执行以下操作:

public function(

string $parameterA,

int $parameterB,

Foo $objectfoo,

) {

// …

}

从接口 创立DateTime 对象

你已经 能够 使用 DateTime::createFromImmutable($immutableDateTime) 从 DateTimeImmutable 对象 创立一个 DateTime 对象, 而另一种方 法令更加取巧 。通过增加DateTime::createFromInterface()和DatetimeImmutable::createFromInterface()现在有一种通用的 步骤 能够将DateTime和DatetimeImmutable对象 彼此转换 。

DateTime::createFromInterface(DateTimeInterface $other);

DateTimeImmutable::createFromInterface(DateTimeInterface $other);