PHP 8, eine neue Hauptversion von PHP, wird voraussichtlich am 3. Dezember 2020 veröffentlicht, was bedeutet, dass es keine PHP 7.5-Version geben wird. PHP8 befindet sich derzeit in einer sehr aktiven Entwicklungsphase, sodass sich in den nächsten Monaten möglicherweise viel ändern wird.
In diesem Artikel werde ich eine aktuelle Liste der erwarteten neuen Funktionen, Leistungsverbesserungen und bahnbrechenden Änderungen führen. Da es sich bei PHP 8 um eine neue große Version handelt, ist die Wahrscheinlichkeit höher, dass Ihr Code beschädigt wird. Wenn Sie immer die neueste PHP-Version verwenden, ist das Upgrade relativ einfach, da die meisten wichtigen Änderungen in der Version 7.* veraltet sind.
Zusätzlich zu den großen Änderungen bringt PHP 8 auch einige tolle neue Funktionen mit, wie z. B. JIT-Compiler, Union-Typen, Eigenschaften und mehr.
Wenn Sie mit neuen Funktionen beginnen, denken Sie daran, dass sich PHP8 noch in der aktiven Entwicklung befindet, sodass diese Liste mit der Zeit wachsen wird.
In Anbetracht der Eigenschaften dynamischer PHP-Sprachtypen sind Union-Typen mittlerweile in vielen Situationen sehr nützlich. Ein Union-Typ ist eine Sammlung von zwei oder mehr Typen, was angibt, dass jeder dieser Typen verwendet werden kann.
public function foo(Foo|Bar $input): int|float;
Bitte beachten Sie, dass void
nicht im Union-Typ enthalten ist, da void
„überhaupt kein Rückgabewert“ bedeutet. Alternativ können Unions, die |null
enthalten, mit ?
oder der vorhandenen nullable
-Notation dargestellt werden:
public function foo(Foo|null $foo): void; public function bar(?Bar $bar): void;
JIT – just in time – Der Compiler Es wird erwartet, dass die Leistung deutlich verbessert wird, wenn auch nicht immer im Kontext einer Webanfrage. Es wurde noch kein genaues Benchmarking durchgeführt, aber es kommt definitiv.
Wenn Sie mehr über die Rolle von JIT für PHP erfahren möchten, können Sie hier einen weiteren Artikel lesen, den ich geschrieben habe.
Attribute, in anderen Sprachen oft als Anmerkungen bezeichnet, bieten eine Möglichkeit, Metadaten an einen Dokumentblock zu übertragen, ohne dass eine Analyse erforderlich ist Es. Methoden, die der Klasse hinzugefügt wurden.
Ein kurzer Blick darauf, hier ist ein Beispiel für Immobilien aus dem 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; } }
Wenn Sie mehr darüber erfahren möchten, wie Immobilien funktionieren und wie Sie Ihre eigenen bauen, können Sie darüber lesen Ausführliche Informationen zu diesem Blog-Attribut.
static
-Rückgabetyp Obwohl es bereits möglich ist, self
zurückzugeben, war static
bis PHP 8 kein gültiger Rückgabetyp. Angesichts der dynamischen Typisierung von PHP wird diese Funktion für viele Entwickler sehr nützlich sein.
class Foo { public function test(): static { return new static(); } }
mixed
GenresManche nennen das vielleicht ein notwendiges Übel: mixed
Genres fühlen sich für viele Menschen sehr verwirrend an. Es gibt jedoch ein gutes Argument für die Implementierung: Fehlende Typen führen in PHP zu vielen Situationen:
Funktion gibt nichts oder null zurück
Wir benötigen einen Typ von mehreren Typen
Was wir brauchen, ist ein Typ, der in PHP nicht typgestützt werden kann
Für das oben Genannte Aus diesen Gründen ist das Hinzufügen des Typs mixed
eine tolle Sache. mixed
selbst stellt einen der folgenden Typen dar:
array
bool
callable
int
float
null
object
resource
string
Bitte beachten Sie, dass mixed
nicht nur als Rückgabetyp, sondern auch als Parameter und Attributtyp verwendet werden kann.
Darüber hinaus müssen Sie beachten, dass der Typ mixed
nicht leer sein darf, da der Typ null
bereits mixed
enthält. Der folgende Code löst einen schwerwiegenden Fehler aus:
// 致命错误:混合类型不能为空,null已经是混合类型的一部分。 function bar(): ?mixed {}
throw
Ausdruck Dieser RFC ändert throw
von einer Anweisung in einen Ausdruck, wodurch es möglich ist, Ausnahmen auszulösen an vielen neuen Stellen:
$triggerError = fn () => throw new MyError(); $foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');
Basiert auf dem schwachen Referenz-RFC, der in PHP 7.4 hinzugefügt wurde, neu in PHP 8WeakMaps
(schwache Mapping-Implementierung). WeakMaps
(schwache Zuordnung) behält Verweise auf einige Objekte bei, ohne zu verhindern, dass diese Objekte vom Garbage-Collection-Mechanismus verarbeitet werden.
Am Beispiel von ORM implementieren sie normalerweise Caching, das Verweise auf Entitätsklassen speichert und dadurch die Leistung von Assoziationen zwischen Entitätsklassen verbessert. Solange sich im Cache Verweise auf diese Entitätsklassen befinden, können diese Klassen vom Garbage-Collection-Mechanismus nicht recycelt werden. Auch wenn diese Entitätsklassen nicht mehr an anderer Stelle außer im Cache referenziert werden, werden sie von der Garbage-Collection immer noch nicht verarbeitet Mechanismus.
如果这个缓存层使用了弱引用和弱映射,那么 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);
在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'); // true str_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()
将返回类名。
如下表:
Value | get_debug_type() | gettype() |
---|---|---|
0 | int | integer |
0.1 | float | double |
true | bool | boolean |
false | bool | boolean |
“hello” | string | |
[] | array | |
null | null | NULL |
A class with name “FooBar” | FooBar | object |
An anonymous class | class@anonymous | object |
A resource | resource (xxx) | resource |
A closed resource | resource (closed) |
可以在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 可以指定必须由使用它们的类所实现的抽象方法。需要注意的是: 在 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 应该没那么难。
之前版本在出现类型错误时,PHP 中的用户定义函数已经会抛出 TypeErrors
,但是内部函数不会这么做,而是发出警告并返回 null
。从 PHP 8 开始,内部函数的行为已变得和用户定义函数一致。
许多以前仅触发警告或通知的错误已转换为适当的错误。以下警告已更改。
变量未定义: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 之前的版本中可能已经存在。
根据RFC:当前 PDO 的默认错误模式为静默。这意味着当出现 SQL 错误时,除非开发人员实现了自己的显式错误处理,否则不会发出任何错误或警告,也不会引发任何异常。
此 RFC 将在 PHP 8 中将默认 PDO 错误模式 改为PDO::ERRMODE_EXCEPTION
。
在 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 最终确定。
Das obige ist der detaillierte Inhalt vonNeue Funktionen und große Änderungen in PHP 8. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!