PHP 8 新特性简介
PHP 8在这里!它于2020年11月26日发布。您可以在此处下载。这是新的主要版本,这意味着它将引入一些重大更改,以及许多新函数和性能改进。
由于重大更改,您很有可能需要对代码进行一些更改才能使其在PHP 8上运行。如果您始终与最新版本保持同步,则升级也不应该太很难,因为在7. *版本之前,大多数重大更改都已弃用。不用担心,所有这些弃用都列在这篇文章中。
除重大更改外,PHP 8还带来了一组不错的新函数,例如 JIT编译器,联合类型,属性等。
# Union types RFC
鉴于PHP的动态类型性质,在很多情况下联合类型可能有用。联合类型是两种或多种类型的集合,表示可以使用其中任何一种。
public function foo(Foo|Bar $input): int|float;
请注意, void
永远不能成为联合类型的一部分,因为它表示"没有返回值"。此外,可以使用|null
或使用现有的?
表示法:
public function foo(Foo|null $foo): void;
public function bar(?Bar $bar): void;
# JIT RFC
JIT(及时)编译器有望显着提高性能,尽管并不总是在Web请求的上下文中。我已经在现实的Web应用程序上完成了自己的基准测试,似乎JIT并没有做到这一点如果有的话,在这些PHP项目上有很大的不同。
# The nullsafe operator RFC
如果您熟悉空合并运算符,那么您已经熟悉它的缺点:不会处理方法调用。相反,您需要进行中间检查,或依靠某些框架提供的 options
帮助器:
$startDate = $booking->getStartDate();
$dateAsString = $startDate ? $startDate->asDateTimeString() : null;
通过添加nullsafe运算符,我们现在可以在方法上具有类似于null合并的行为!
$dateAsString = $booking->getStartDate()?->asDateTimeString();
# 命名参数 RFC
命名参数允许您通过指定值名称将值传递给函数,这样您就不必按其顺序考虑在内,您还可以跳过可选参数!
function foo(string $a, string $b, ?string $c = null, ?string $d = null)
{ /* … */ }
foo(
b: 'value b',
a: 'value a',
d: 'value d',
);
# Attributes RFC
属性(在其他语言中通常称为注释)提供了一种向类添加元数据的方法,而无需解析文档块。
快速浏览一下,这是RFC中的属性样式示例:
#[ExampleAttribute]
class Foo
{
#[ExampleAttribute]
public const FOO = 'foo';
#[ExampleAttribute]
public $x;
#[ExampleAttribute]
public function foo(#[ExampleAttribute] $bar) { }
}
#[Attribute]
class ExampleAttribute
{
public $value;
public function __construct($value)
{
$this->value = $value;
}
}
请注意,此基础Attribute
过去被称为PhpAttribute
在原始RFC中,但后来被另一个RFC 更改。
# Match表达式 RFC
您可以称其为 switch
表达式: match
可以返回值,不需要 break
语句,可以组合条件,使用严格的类型比较,不执行任何类型强制。
看起来像这样:
$result = match($input) {
0 => "hello",
'1', '2', '3' => "world",
};
# 增强构造函数 RFC
该RFC添加了语法糖来创建值对象或数据传输对象。现在,PHP可以将它们组合为一个,而不必为它们指定类属性和构造函数。
而不是这样做:
class Money
{
public Currency $currency;
public int $amount;
public function __construct(
Currency $currency,
int $amount,
) {
$this->currency = $currency;
$this->amount = $amount;
}
}
您现在可以执行以下操作:
class Money
{
public function __construct(
public Currency $currency,
public int $amount,
) {}
}
# 新static返回类型 RFC
虽然已经可以返回 self
,但 static
直到PHP 8才是有效的返回类型。考虑到PHP具有动态类型化的特性,它对许多开发人员都非常有用。
class Foo
{
public function test(): static
{
return new static();
}
}
# 新 mixed 类型 RFC
mixed
类型会导致许多人产生混杂的感觉。不过,有一个很好的论据:缺少类型可能意味着在PHP中会有很多事情
请注意,mixed
也可以用作参数或属性类型,而不仅仅是返回类型。
另请注意,由于mixed
已包含null
,不允许将其设为可空值。以下内容将触发错误:
// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function bar(): ?mixed {}
# Throw expression RFC
该RFC将 throw
从一个语句更改为一个表达式,这使得在许多新地方引发异常成为可能:
$triggerError = fn () => throw new MyError();
$foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');
# Weak maps RFC
基于PHP 7.4中添加的弱引用RFC , WeakMap
实现。 WeakMap
保存对对象的引用,不会阻止这些对象被垃圾回收。
以ORM为例,它们通常实现缓存,该缓存保存对实体类的引用,以提高实体之间关系的性能。只要该高速缓存具有对它们的引用,就不能对其进行垃圾回收,即使该高速缓存是引用它们的 only 事物也是如此。
如果此缓存层使用了弱引用和映射,则PHP将在没有其他引用的情况下对这些对象进行垃圾收集。尤其是在ORM的情况下,它可以管理一个请求中的数百个(如果不是数千个)实体。弱映射可以提供一种更好,更资源友好的方式来处理这些对象。
这是弱映射的样式,这是RFC中的一个示例:
class Foo
{
private WeakMap $cache;
public function getSomethingWithCaching(object $obj): object
{
return $this->cache[$obj]
??= $this->computeSomethingExpensive($obj);
}
}
# 在对象上允许 ::class RFC
一个小的但有用的新函数:现在可以在对象上使用 ::class
,而不必使用get_class()
。其工作方式与 get_class()
相同。
$foo = new Foo();
var_dump($foo::class);
# Non-capturing catches RFC
每当您想在PHP 8之前捕获异常时,无论是否使用该变量,都必须将其存储在变量中。使用非捕获的捕获,您可以忽略变量,所以代替这个:
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
作为捕获类型。
# 从接口创建DateTime对象
您已经可以通过 DateTimeImmutable 创建 DateTime 对象对象。DateTime::createFromInterface(DateTimeInterface $other);
DateTimeImmutable::createFromInterface(DateTimeInterface $other);
# 新的Stringable接口 RFC
Stringable
接口可用于提示任何实现__toString()
。每当一个类实现__toString()
时,它都会自动实现接口,无需手动实现。
class Foo
{
public function __toString(): string
{
return 'foo';
}
}
function bar(string|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()
and str_ends_with()
函数 RFC
现在已在核心中添加了这两个函数。
str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true
# 新 fdiv()
函数 RFC
新的 fdiv()
函数的作用类似于 fmod()
和 intdiv()
函数,该函数允许除以0。得到的不是错误,而是错误 INF
, -INF
或 NAN
#新 get_resource_id()
函数 PR
资源是PHP中的特殊变量,是指外部资源。一个示例是MySQL连接,另一个示例是文件句柄。
这些资源中的每一个都分配有一个ID,尽管以前唯一知道该ID的方法是将资源转换为 int
:
$resourceId = (int) $resource;
PHP 8添加了 get_resource_id ()
函数,从而使此操作更加明显且类型安全:
$resourceId = get_resource_id($resource);
# 增强抽象方法 RFC
特性可以指定必须由使用它们的类实现的抽象方法。需要注意的是:在PHP 8之前,这些方法实现的语法尚未经过验证。以下是有效的:
trait Test {
abstract public function test(int $input): int;
}
class UsesTrait
{
use Test;
public function test($input)
{
return $input;
}
}
当使用特征并实现其抽象方法时,PHP 8将执行正确的方法语法验证。这意味着您需要编写以下代码:
class UsesTrait
{
use Test;
public function test(int $input): int
{
return $input;
}
}
# 串联优先 RFC
尽管PHP 7.4中已弃用该更改,但现在已生效。如果您要编写这样的内容:
echo "sum: " . $a + $b;
PHP以前会这样解释它:
echo ("sum: " . $a) + $b;
PHP 8将使其如此解释:
echo "sum: " . ($a + $b);
# 更严格的类型检查 RFC
<hljs类型>在PHP 8之前,可以在数组,资源或对象上应用算术或按位运算符。这不可能了,将抛出 TypeError
:
[] % [42];
$object + 4;
# Reflection changes
不推荐使用几种反射方法:
现在,您应该使用 ReflectionType
来获取有关参数类型的信息:
$reflectionParameter->getType()->allowsNull();
如果类型是单一类型,则 ReflectionParameter::getType()返回 ReflectionNamedType
的实例
$reflectionParameter->getType()->getName();
$reflectionParameter->getType()->isBuiltin();
但是,如果该类型是联合类型,则将获得 ReflectionUnionType
的实例,该实例可以为您提供一个 ReflectionNamedType
像这样:
$reflectionParameter->getType()->getTypes();
可以使用 instanceof
检查来检查类型是否为联合:
if ($reflectionParameter->getType() instanceof ReflectionNamedType) {
// It's a single type
}
if ($reflectionParameter->getType() instanceof ReflectionUnionType) {
// It's a union type
}
接下来,反射类的三个方法语法已更改:
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);
链接:https://www.learnfk.com/article-new-in-php-8
来源:Learnfk无涯私塾网