新闻动态

新的PHP8中的改进

行业资讯 发布者:swl 2020-08-05 09:36 访问量:158

新的 PHP 主要版本 PHP8 预计将于 2020 年底发布。它现在正处于非常活跃的开发中,所以在接下来的几个月里,开发速度和开发进程可能会有很大的变化。

在这篇文章中,我会罗列出 PHP8 中会发生的一些改变:新功能、性能改进和突破性变化。因为 PHP8 是一个新的主要版本,所以代码及语法向下兼容性会更低。如果您一直保持与最新版本保持同步,那么升级应该不会太难,因为大多数突破性的更改在 7.* 版本中都已弃用。

除了突破性的变化,PHP8 还带来了一些不错的新特性,比如 JIT 编译器和 union types,当然还有其它更多的特性。

新特性

从新特性开始说起,但是 PHP8 仍在积极开发中,因此这个清单将随着时间的推移而增长。

联合类型(Union types) RFC

考虑到 PHP 的动态类型特性,联合类型在很多情况下都很有用。联合类型是两个或多个类型的集合,这些类型指示可以使用这两个类型中的任何一个。

publicfunctionfoo(Foo|Bar$input):int|float;我怎么感觉这个和C语言里的联合体有点相似。

请注意,void 永远不能是联合类型的一部分,因为它表示“根本没有返回值”。此外,可以使用|NULL或使用现有的?。

publicfunctionfoo(Foo|null$foo):void;

publicfunctionbar(?Bar$bar):void;

JIT RFC

JIT-Just-In-Time 编译器承诺显著提高性能,尽管在 Web 应用可能没有较大的好处。在这一点上还没有任何准确的基准,但它们肯定会出现的。

静态返回类型(Static return type) RFC

虽然已经可以返回 self ,但在 PHP8 之前,静态不是有效的返回类型。考虑到 PHP 的动态类型特性,它对许多开发人员都很有用。

classFoo

{

publicfunctiontest():static{returnnewstatic();}

}

弱映射(Weak maps) RFC

基于在 PHP 7.4 中添加的 WeakRefs RFC 的基础上,在 PHP 8中 添加了 WeakMap 实现。WeakMap 包含对对象的引用,这不会阻止这些对象被垃圾回收。

以 ORM 为例,它们经常实现包含对实体类的引用的缓存,以提高实体之间关系的性能。这些实体对象不能被垃圾回收,只要该缓存有对它们的引用,即使缓存是唯一引用它们的东西。

如果该缓存层改为使用弱引用和映射,则 PHP 将在其他对象不再引用这些对象时对它们进行垃圾回收。特别是在 ORM 的情况下,它可以在一个请求中管理数百个(如果不是数千个)实体;弱映射可以提供一种更好、更资源友好的方式来处理这些对象。

以下是 Weak maps 的用法,RFC 中的一个示例:

classFoo{privateWeakMap$cache;publicfunctiongetSomethingWithCaching(object$obj):object{return$this->cache[$obj]??=$this->computeSomethingExpensive($obj);}

}

可以在对象上使用::classRFC

一个小而有用的新特性:现在可以对对象使用::class,而不必对它们使用get_class()。它的工作方式与get_class()相同。

$foo=newFoo();var_dump($foo::class);创建 DateTime 对象的接口

您已经可以使用

DateTime::createFromImmutable($immutableDateTime),

从DateTimeImmutable对象创建DateTime

对象,但是反过来很棘手。

通过添加DateTimecreateFromInterface()

和DatetimeImmutable::createFromInterface(),

现在有了一种将DateTime和DateTimeImmutable对象相互转换的通用方法。

DateTime::createFromInterface(DateTimeInterface$other);

DateTimeImmutable::createFromInterface(DateTimeInterface$other);

新的 Stringable 接口 RFC

Stringable接口可用于键入提示任何字符串或实现__toString()。此外,每当类实现__toString()时,它都会自动在幕后实现接口,不需要手动实现它。

classFoo

{

publicfunction__toString():string{return'foo';}

}

functionbar(Stringable$stringable){/* … */}

bar(newFoo());bar('abc');

新的 str_contains() 函数 RFC

有些人可能会说这是早就应该实现的功能,但是我们最终不必再依赖 strpos() 来知道一个字符串是否包含另一个字符串。

以前:

if(strpos('string with lots of words','words')!==false){/* … */}现在:

if(str_contains('string with lots of words','words')){/* … */}新的 fdiv() 函数 PR

新的 fdiv() 函数的作用类似于 fmod() 和 intdiv() 函数,它们允许被 0 整除。您将得到 INF、-INF 或 NaN ,而不是错误,具体取决于大小写。

新的 get_debug_type() 函数 RFC

get_debug_type() 返回一个变量的类型。听起来像是 gettype() 可以实现的功能。get_debug_type() 为数组、字符串、匿名类和对象返回更有用的输出。

例如,在类 ooBar 上调用 gettype() 将返回 Object。使用 get_debug_type() 将返回类名。

可以在 RFC 中找到 get_debug_type() 和 gettype() 之间差异的完整列表。

改进 traits 里的抽象方法 RFC

traits 可以指定必须由使用它们的类实现的抽象方法。但是有一个警告:在 PHP8 之前,这些方法实现的签名没有经过验证。在以下代码中有效:

traitTest

{

abstractpublicfunctiontest(int$input):int;

}

classUsesTrait

{

useTest;publicfunctiontest($input){return$input;}

}

在使用 traits 并实现其抽象方法时,PHP8 将执行正确的方法签名验证。这意味着您需要改写以下内容:

classUsesTrait

{

useTest;publicfunctiontest(int$input):int{return$input;}

}

token_get_all() 的对象接口 RFC

函数的作用是:返回值的是一个数组。此 RFC 使用 PhpToken::getall() 方法添加一个 PhpToken 类。此实现使用对象,而不是普通值。它消耗更少的内存,更容易阅读。

变量语法调整 RFC

来自 RFC:“统一变量语法RFC解决了PHP变量语法中的一些不一致问题”,这个 RFC 打算解决少数被忽略的情况。

内部函数的类型批注

很多人都参与到为所有内部函数添加适当类型注释的工作中。这是一个长期存在的问题,通过在以前版本中对 PHP 所做的所有更改,最终可以解决这个问题。这意味着内部函数和方法在反射中将具有完整的类型信息。

统一错误类型 RFC

PHP 中的用户定义函数已经抛出 TypeErrors,但是内部函数没有抛出 TypeErrors,而是发出警告并返回 NULL。从 PHP8 开始,内部函数的行为已经保持一致。

重新分类 zend engine 报错 RFC

许多以前只触发警告或通知的错误已转换为适当的错误。以下警告已更改。

未定义变量:错误异常而不是通知。未定义的数组索引:警告而不是通知。被零除:DivisionByZeroError 异常而不是警告。尝试递增/递减非对象的属性‘%s’:错误异常而不是警告。试图修改非对象的属性‘%s’:错误异常而不是警告。尝试分配非对象的属性‘%s’:错误异常而不是警告。从空值创建默认对象:错误异常而不是警告。正在尝试获取非对象的属性‘%s’:警告而不是通知。未定义属性:%s::$%s:警告而不是通知。无法将元素添加到数组,因为下一个元素已被占用:错误异常而不是警告。无法取消设置非数组变量中的偏移量:错误异常而不是警告。不能将标量值用作数组:错误异常而不是警告。只能解包数组和遍历:TypeError 异常而不是警告。为 foreach() 提供的参数无效:TypeError 异常而不是警告。偏移类型非法:TypeError 异常而不是警告。isset 中的偏移类型非法或为空:TypeError 异常而不是警告。未设置中的偏移类型非法:TypeError 异常而不是警告。数组到字符串的转换:警告而不是通知。资源 ID#%d 用作偏移量,转换为整数(%d):警告而不是通知。发生字符串偏移量转换:警告而不是通知。未初始化的字符串偏移量:%d:警告而不是通知。无法将空字符串分配给字符串偏移量:错误异常而不是警告默认错误报告级别

现在是 E_ALL,而不是除 E_NOTICE 和 E_DEVERATED 之外的所有内容。这意味着可能会弹出许多以前被悄悄忽略的错误,尽管在 PHP8 之前可能已经存在。

@运算符不再忽略致命错误

此更改可能会揭示在 PHP8 之前隐藏的错误。请确保在生产服务器上设置 display_errors=off !

串联优先级 RFC

虽然在 PHP7.4 中已不推荐使用,但此更改现在生效。如果你这样写的话:

echo"sum: ".$a+$b;PHP 以前会这样解释它:

echo("sum: ".$a)+$b;PHP 8 将会这样解释它:

echo"sum: ".($a+$b);反射方法签名更改

反射类的三个方法签名已更改:

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);

其他

在PHP7.*开发过程中,被用的 RFC,现在已在PHP8中完成。




关键字:

http://m.chenzhankj.com/hyzx/692.html