ホームページ >バックエンド開発 >PHP8 >PHP 8 の新機能と大きな変更点

PHP 8 の新機能と大きな変更点

Guanhui
Guanhui転載
2020-06-30 11:32:386142ブラウズ

PHP 8 の新機能と大きな変更点

PHP の新しいメジャー バージョンである PHP 8 は、2020 年 12 月 3 日にリリースされる予定です。つまり、PHP 7.5 バージョンは存在しません。 PHP8 は現在非常に活発な開発段階にあるため、今後数か月で状況が大きく変わる可能性があります。

この記事では、予想される新機能、パフォーマンスの向上、重大な変更の最新リストを維持します。 PHP 8 は新しい大きなバージョンであるため、コードが破損する可能性が高くなります。常に最新バージョンの PHP を実行している場合、ほとんどの重大な変更は 7.* バージョンで非推奨になっているため、アップグレードは比較的簡単です。

大きな変更に加えて、PHP 8 には、JIT コンパイラー、共用体型、プロパティなどのいくつかの優れた新機能も導入されています。

新機能

まず新機能から始めますが、PHP8 はまだ開発中であるため、このリストは時間の経過とともに増加することを覚えておいてください。

共用体型

PHP 動的言語型の特性を考慮すると、現在、共用体型は多くの状況で非常に役立ちます。共用体型は 2 つ以上の型のコレクションであり、いずれかの型を使用できることを示します。

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

void は「戻り値がまったくない」ことを意味するため、ユニオン型には含まれないことに注意してください。あるいは、nullable を含む共用体は、|null または既存の ? 表記を使用して表すことができます: <pre class="brush:php;toolbar:false">public function foo(Foo|null $foo): void; public function bar(?Bar $bar): void;</pre>

JIT

JIT — ジャストインタイム — コンパイラーは、常に Web リクエストのコンテキストにあるわけではありませんが、パフォーマンスを大幅に向上させることが期待されています。正確なベンチマークはまだ行われていませんが、確実に実現されるでしょう。

PHP における JIT の役割について詳しく知りたい場合は、ここで私が書いた別の記事を読んでください。

属性

属性は、他の言語では

注釈

と呼ばれることが多く、ドキュメント ブロックを解析せずにメタデータをドキュメントに転送する方法を提供します。 . クラスにメソッドが追加されました。 簡単に見てみるために、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 の動的に型指定される性質を考慮すると、この機能は多くの開発者にとって非常に役立ちます。 <pre class="brush:php;toolbar:false">class Foo {     public function test(): static     {         return new static();     } }</pre>

New

mixed Typeこれを必要悪と呼ぶ人もいるかもしれません:

mixed

Type は多くの人を作ります それはとても感じます混乱する。ただし、実装を支持する良い議論があります。型が欠落していると、PHP で多くの状況が発生します。

    関数が何も返さない、または null を返す
  • 複数の型のうちの 1 つの型が必要です
  • 必要なのは、PHP でタイプヒントできない型です
  • For上記の理由から、
mixed

タイプを追加することは素晴らしいことです。 mixed 自体は、次のいずれかの型を表します:

  • array

  • bool

  • ##呼び出し可能
  • ##int
  • float
  • ##null

  • オブジェクト

  • リソース

  • 文字列

  • 次のことに注意してください 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 の実装

WeakMaps (弱いマッピング) は 8 で追加されました。 WeakMaps

(弱いマッピング) は、一部のオブジェクトへの参照を維持し、これらのオブジェクトがガベージ コレクション メカニズムによって処理されるのを妨げません。

ORM を例に挙げると、通常、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()现在有一种通用的方法可以将DateTimeDatetimeImmutable对象相互转换。

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

新增 get_debug_type() 函数

get_debug_type()返回变量的类型,听起来好像跟 gettype() 的作用一样啊?get_debug_type()  可以为数组,字符串,匿名类和对象返回更有用的输出信息。

例如,在类\ Foo \ Bar上调用gettype()将返回object,而使用get_debug_type()将返回类名。

如下表:

##「こんにちは」文字列[]配列#null「」という名前のクラスFoo\Bar”匿名クラスリソースクローズド リソース

可以在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 中的弃用
get_debug_type() gettype()
0 int integer
0.1 float double
true bool boolean
false bool boolean


null NULL
Foo\Bar オブジェクト
class@anonymous オブジェクト
リソース (xxx) リソース
リソース (終了)

以上がPHP 8 の新機能と大きな変更点の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
前の記事:なし次の記事:PHP 8 能有多快?(性能测试)