在这篇文章中,我会坚持一个最新的清单列表,列出估量会涌现的新特性、性能提升和打破性的变革。由于 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 App\Attributes\ExampleAttribute;<<ExampleAttribute>>class Foo{<<ExampleAttribute>>public const FOO = 'foo';<<ExampleAttribute>>public $x;<<ExampleAttribute>>public function foo(<<ExampleAttribute>> $bar) { }}
<<PhpAttribute>>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 本身代表下列类型中的任一类型:
arrayboolcallableintfloatnullobjectresourcestring请把稳,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);
新增 Stringable接口
Stringable接口可用于键入提示任何字符串或实现__ toString()的内容。此外,每当一个类实现__ toString()时,它就会自动实现后台接口,而无需手动实现。
class Foo{public function __toString(): string{return 'foo';}}function bar(Stringable $stringable) { / … / }bar(new Foo());bar('abc');
新增 str_contains() 函数 rfc
有些人可能会说这是早该发生的,但我们终极不必再依赖strpos来知道一个字符串是否包含另一个字符串。
无需这样做:
if (strpos('string with lots of words', 'words') !== false) { / … / }
你可以这样做:
if (str_contains('string with lots of words', 'words')) { / … / }
新增 str_starts_with() 和 str_ends_with() 函数
这是其余两个早该涌现的函数,现在已在核心函数中添加了这两个函数。
str_starts_with('haystack', 'hay'); // truestr_ends_with('haystack', 'stack'); // true
新增 fp() 函数
新的fp()函数的浸染类似于fmod()和intp()函数,它们可以除以0。视情形而定,将得到INF,-INF或NAN。
新增 get_debug_type() 函数
get_debug_type()返回变量的类型,听起来彷佛跟 gettype() 的浸染一样啊?get_debug_type() 可以为数组,字符串,匿名类和工具返回更有用的输出信息。
例如,在类\ Foo \ Bar上调用gettype()将返回object,而利用get_debug_type()将返回类名。
如下表:
可以在RFC中找到get_debug_type()和gettype()之间的差异的完全列表。
新增 get_resource_id() 函数
资源是PHP中的分外变量,指的是外部资源。一个示例是MySQL连接,另一个是文件句柄。
这些资源中的每一个都分配有一个ID,然而在这之前,如果想获取某资源的ID,唯一方法是将资源转换为int:
$resourceId = (int) $resource;
PHP 8添加了get_resource_id()函数,使此操作更加明显且类型安全:
$resourceId = get_resource_id($resource);
Traits 改进中的抽象方法
Traits 可以指定必须由利用它们的类所实现的抽象方法。须要把稳的是:在 PHP 8 之前,尚未验证这些方法已经实现的标识。以下内容有效:
trait Test {abstract public function test(int $input): int;}class UsesTrait{use Test;public function test($input){return $input;}}
当利用 Traits 并实现其抽象方法时,PHP 8将实行适当的方法进行标识验证抽象方法是否确实被实现。这意味着您须要编写以下代码:
class UsesTrait{use Test;public function test(int $input): int{return $input;}}
token_get_all() rfc的工具实现
token_get_all()函数返回一个值数组,该RFC利用PhpToken :: getAll()方法新增了PhpToken类。此实实际用于工具而不是普通值。它花费更少的内存,并且更易于阅读。
可变语法调度
在RFC中:“统一变量语法RFC办理了PHP变量语法中的许多不一致之处。该RFC旨在办理一小部分被忽略的情形。”
内部函数的类型表明
许多人 投入 了为所有内部函数添加适当的类型注释的事情。这是一个长期存在的问题,终极可以通过以前版本中对PHP所做的所有变动来办理。这意味着内部函数和方法将在反命中具有完全的类型信息。
重大变革
如前所述:这是一个重大更新,因此会有重大变革。最好的办法是查看 升级 文档中所列的重大变革的完全列表。
许多这些打破性的变动在以前的 7. 版本中已被弃用,因此如果你多年来一贯保持 PHP 在最新状态,升级到 PHP 8 该当没那么难。
同等的类型缺点 rfc
之前版本在涌现类型缺点时,PHP 中的用户定义函数已经会抛出 TypeErrors,但是内部函数不会这么做,而是发出警告并返回 null。从 PHP 8 开始,内部函数的行为已变得和用户定义函数同等。
重新分类的引擎警告 rfc
许多以前仅触发警告或关照的缺点已转换为适当的缺点。以下警告已变动。
变量未定义:Error 非常代替关照数组索引未定义:警告代替关照除以零:pisionByZeroError 非常代替警告考试测验添加/移除非工具的属性 '%s' :Error 非常代替警告试修正非工具的属性 '%s' :Error 非常代替警告考试测验分配非工具的属性 '%s' :Error 非常代替警告从空值创建默认工具:Error 非常代替警告考试测验获取非工具的属性 '%s' :警告代替关照未定义的属性:%s::$%s:警告代替关照法添加元素到数组,由于下一个元素已被占用:Error 非常代替警告无法在非数组变量中销毁偏移量:Error 非常代替警告无法将标量值用作数组:Error 非常代替警告只有数组和 Traversables 可以被解包:TypeError 非常代替警告为 foreach() 供应了有效的参数:TypeError 非常代替警告偏移量类型造孽:TypeError 非常代替警告isset 或 empty 中的偏移量类型造孽:TypeError 非常代替警告unset 中的偏移量类型造孽:TypeError 非常代替警告数组到字符串的转换:警告代替关照资源 ID#%d 用作偏移量,转换为整数 (%d):警告代替关照发生字符串偏移量转换:警告代替关照未初始化的字符串偏移量:%d:警告代替关照无法将空字符串分配给字符串偏移量:Error 非常代替警告供应的资源不是有效的流资源:TypeError 非常代替警告@ 运算符不再使致命缺点不提醒
此变动可能会使 PHP 8 之前的版本被 @ 隐蔽的缺点再次显示出来。请确保在生产做事器上设置了 display_errors=Off !
默认缺点报告级别
现在的默认缺点报告级别是 E_ALL 而不是之前的除 E_NOTICE 和 E_DEPRECATED 的所有内容。这意味着可能会弹出许多缺点,这些缺点以前曾被忽略,只管在 PHP 8 之前的版本中可能已经存在。
默认 PDO 缺点模式 rfc
根据RFC:当前 PDO 的默认缺点模式为静默。这意味着当涌现 SQL 缺点时,除非开拓职员实现了自己的显式缺点处理,否则不会发出任何缺点或警告,也不会引发任何非常。
此 RFC 将在 PHP 8 中将默认 PDO 缺点模式 改为PDO::ERRMODE_EXCEPTION 。
串联优先级 rfc
在 PHP 7.4 中已废弃的同时,此变更开始生效。如果你像这样子书写:
echo "sum: " . $a + $b;
PHP 以前会如是理解:
echo ("sum: " . $a) + $b;
PHP 8 将这么做故理解为此:
echo "sum: " . ($a + $b);
更严格的算术和位运算类型检讨
PHP 8 以前,算术或位运算符用于数组、资源或工具是可接管的。现在不再可接管,并会抛出一个 类型缺点 :
[] % [42];$object + 4;
反射方法署名变更
反射类的 3 个方法署名已变更:
ReflectionClass::newInstance($args);ReflectionFunction::invoke($args);ReflectionMethod::invoke($object, $args);
现在已变成:
ReflectionClass::newInstance(...$args);ReflectionFunction::invoke(...$args);ReflectionMethod::invoke($object, ...$args);
升级指南指定,如果要扩展这些类,并且仍想同时支持 PHP 7 和 PHP 8,则许可以下署名:
ReflectionClass::newInstance($arg = null, ...$args);ReflectionFunction::invoke($arg = null, ...$args);ReflectionMethod::invoke($object, $arg = null, ...$args);
几个弃用
在PHP 7. 的开拓期间,添加了几个弃用版本,这些弃用已于 PHP 8 终极确定。
PHP 7.2 中的弃用
PHP 7.3 中的弃用
PHP 7.4 中的弃用