PHP의 새로운 주요 버전인 PHP 8은 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
는 공용체 유형에 포함되지 않는다는 점에 유의하세요. 또한 nullable
을 포함하는 공용체는 |null
또는 기존 ?
표기법을 사용하여 표현할 수 있습니다. void
,因为void
表示的含义是“根本没有返回值”。 另外,可以使用 |null
或者现有的 ?
表示法来表示包含 nullable
的联合体 :
public function foo(Foo|null $foo): void; public function bar(?Bar $bar): void;
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
本身代表下列类型中的任一类型:
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
class Foo { private WeakMap $cache; public function getSomethingWithCaching(object $obj): object { return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj); } }
JIT
🎜🎜 JIT — 바로 시간 — 컴파일러는 웹 요청의 맥락에서 항상 그런 것은 아니지만 성능을 크게 향상시킬 것으로 예상됩니다. 아직 정확한 벤치마킹이 이루어지지 않았지만, 확실히 나올 것입니다. 🎜🎜PHP에서 JIT의 역할에 대해 더 알고 싶다면 여기에 제가 쓴 다른 기사를 읽어보세요. 🎜🎜🎜속성 🎜🎜🎜다른 언어에서 종종 주석이라고 불리는 속성은 문서 덩어리를 구문 분석할 필요 없이 클래스에 메타데이터를 추가하는 방법을 제공합니다. 🎜🎜다음은 RFC의 속성 예입니다. 🎜$foo = new Foo(); var_dump($foo::class);
try { // Something goes wrong } catch (MySpecialException $exception) { Log::error("Something went wrong"); }
static
반환 유형 🎜🎜🎜self
를 반환하는 것이 가능하지만 static
은 PHP 8까지 유효한 반환 유형이 아닙니다. PHP의 동적 유형 특성을 고려하면 이 기능은 많은 개발자에게 매우 유용할 것입니다. 🎜try { // Something goes wrong } catch (MySpecialException) { Log::error("Something went wrong"); }
혼합
유형 🎜🎜🎜어떤 사람들은 필요악이라고 부를 수도 있습니다. 혼합
유형은 많은 사람들에게 매우 혼란스럽게 느껴집니다. 그러나 이를 구현하는 데 유리한 주장이 있습니다. 유형이 누락되면 PHP에서 많은 상황이 발생합니다. 🎜mixed
유형을 추가하는 것은 좋은 일입니다. mixed
자체는 다음 유형 중 하나를 나타냅니다: 🎜array
🎜bool
🎜호출 가능
🎜int
🎜 li> float
🎜null
🎜객체
🎜리소스
🎜문자열
🎜혼합 /code >는 반환 유형뿐만 아니라 매개변수 및 속성 유형으로도 사용될 수 있습니다. 🎜🎜또한 <code>mixed
유형에는 이미 null
이 포함되어 있으므로 mixed
유형은 비워둘 수 없다는 점에 유의해야 합니다. 다음 코드는 치명적인 오류를 유발합니다. 🎜public function( string $parameterA, int $parameterB, Foo $objectfoo, ) { // … }
throw
표현식 🎜🎜🎜이 RFC는 throw
를 명령문에서 표현식으로 변경하여 Exception Throw를 사용할 수 있게 합니다. 새로운 위치: 🎜DateTime::createFromInterface(DateTimeInterface $other); DateTimeImmutable::createFromInterface(DateTimeInterface $other);
WeakMaps
(약한 매핑) 구현이 PHP 8에 추가되었습니다. 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);
在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 |
“안녕하세요” | string | |
[] | array |
|
null | null | NULL |
이름이 "FooBar"인 클래스 | FooBar | object |
익명 클래스 | class@anonymous | object |
A 리소스 | resource (xxx) | resource |
A 휴무 리소스 | 리소스(닫음) |
可以在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 最终确定。
위 내용은 PHP 8의 새로운 기능과 주요 변경 사항의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!