PHP 8 有哪些值得期待的新特性

Souleigh ✨ 等级 541 0 0

新的 PHP 主要版本 PHP8 预计将于 2020 年底发布。

它现在正处于非常活跃的开发中,所以在接下来的几个月里,开发速度和开发进程可能会有很大的变化。

在这篇文章中,我会罗列出 PHP8 中会发生的一些改变:新功能、性能改进和突破性变化。

因为 PHP8 是一个新的主要版本,所以代码及语法向下兼容性会更低。

如果您一直保持与最新版本保持同步,那么升级应该不会太难,因为大多数突破性的更改在 7.* 版本中都已弃用。

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

新特性

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

联合类型 (Union types) RFC

考虑到 PHP 的动态类型特性,联合类型在很多情况下都很有用。

联合类型是两个或多个类型的集合,这些类型指示可以使用这两个类型中的任何一个。

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

我怎么感觉这个和 C 语言里的联合体有点相似。

请注意,void 永远不能是联合类型的一部分,因为它表示 “根本没有返回值”。

此外,可以使用|NULL或使用现有的

public function foo(Foo|null $foo): void;

public function bar(?Bar $bar): void; 

JIT RFC

JIT-Just-In-Time 编译器承诺显著提高性能,尽管在 Web 应用可能没有较大的好处。

在这一点上还没有任何准确的基准,但它们肯定会出现的。

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

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

class Foo
{
    public function test(): static
    {
        return new static();
    }
} 

弱映射 (Weak maps) RFC

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

以 ORM 为例,它们经常实现包含对实体类的引用的缓存,以提高实体之间关系的性能。

这些实体对象不能被垃圾回收,只要该缓存有对它们的引用,即使缓存是唯一引用它们的东西。

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

以下是 Weak maps 的用法,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); 

创建 DateTime 对象的接口

您已经可以使用 DateTime::createFromImmutable($immutableDateTime),从 DateTimeImmutable 对象创建DateTime对象,但是反过来很棘手。

通过添加 DateTime::createFromInterface() 和 DatetimeImmutable::createFromInterface(),现在有了一种将 DateTime 和 DateTimeImmutable 对象相互转换的通用方法。

DateTime::createFromInterface(DateTimeInterface $other);

DateTimeImmutable::createFromInterface(DateTimeInterface $other); 

新的 Stringable 接口 RFC

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')) { /* … */ } 

新的 fdiv () 函数 PR

新的 fdiv () 函数的作用类似于 fmod () 和 intdiv () 函数,它们允许被 0 整除。

您将得到 INF、-INF 或 NaN ,而不是错误,具体取决于大小写。

新的 get_debug_type () 函数 RFC

get_debug_type () 返回一个变量的类型。

听起来像是 gettype () 可以实现的功能。

get_debug_type () 为数组、字符串、匿名类和对象返回更有用的输出。

例如,在类 \foo\Bar 上调用 gettype () 将返回 Object。

使用 get_debug_type () 将返回类名。

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

改进 traits 里的抽象方法 RFC

traits 可以指定必须由使用它们的类实现的抽象方法。

但是有一个警告:在 PHP8 之前,这些方法实现的签名没有经过验证。

在以下代码中有效:

trait Test {
    abstract public function test(int $input): int;
}

class UsesTrait
{
    use Test;

    public function test($input)
    {
        return $input;
    }
} 

在使用 traits 并实现其抽象方法时,PHP8 将执行正确的方法签名验证。

这意味着您需要改写以下内容:

class UsesTrait
{
    use Test;

    public function test(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 中完成。

收藏
评论区

相关推荐

php指的是什么?
PHP(全称:Hypertext Preprocessor,即“PHP:超文本预处理器”)是一种开源的通用计算机脚本语言,尤其适用于网络开发并可嵌入H
PHP 8 有哪些值得期待的新特性
新的 PHP 主要版本 PHP8 预计将于 2020 年底发布。 它现在正处于非常活跃的开发中,所以在接下来的几个月里,开发速度和开发进程可能会有很大的变化。 在这篇文章中,我会罗列出 PHP8 中会发生的一些改变:新功能、性能改进和突破性变化。 因为 PHP8 是一个新的主要版本,所以代码及语法向下兼容性会更低。 如果您一直保持与最新版本保持同步,
PHP程序员必须会的 45 个PHP 面试题(第二部分)
Q20: require\_once 和 require 在什么场景下使用? Topic: PHP Difficulty: ⭐⭐⭐ require\_once() 作用与 require() 的作用是一样的,都是引用或包含外部的一个 php 文件,require\_once() 引入文件时会检查文件是否已包含,如果已包含,不再包含 (requir
请纠正这5个PHP编码小陋习
在做过大量的代码审查后,我经常看到一些重复的错误,以下是纠正这些错误的方法。 在循环之前测试数组是否为空 $items ; // ... if (count($items) 0) { foreach ($items as $item) { // process on $item ...
使用PHP生成网站Sitemap,Laravel风格
PHP生成网站Sitemap,包含默认、分类、文章、标签、profile等 <?php namespace AppLibs; use AppS
2017最新PHP经典面试题目汇总(上篇)
2017最新PHP经典面试题目汇总(上篇) 2017最新PHP经典面试题目汇总(上篇) 本文章将持续更新,希望能在评论区发表自己的见解和认为比较经典的题目,后续笔者会在适当的节点对本文章进行分类和层次
nginx安全配置
安全是一个重要的问题,必须引起注意。 1. nginx介绍 nginx本身不能处理PHP(http://www.ttlsa.com/php/ "php"),它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端。nginx一般是把请求发fastcgi管理进程处理,fastcgi管理进程选择cgi子
为什么要从php 加入到 go 的潮流
为何我要说加入go开发是一种潮流,尤其是对于php开发人员,我加入了很多go的开发群或者爱好群,发现大部分人都是从php过来的,原本google开发golang是想让更多的c/c人员来使用。 PHP 语言作为当今最热门的网站程序开发语言,它也是我多年来一直使用的语言,它具有成本低、速度快、可移植性好、 内置丰富的函数库等优点,因此被越来越多的企业应用于网站
PHP学习笔记之PHP的函数应用
目录一、函数的定义 二、自定义函数 三、函数的工作原理和结构化编程 四、PHP变量的范围 五、声明及应用各种形式的PHP函数 六、递归函数 七、使用自定义函数库 一、函数的定义一个被命名的、独立的代码段,它执行特定的任务,并可能给调用它的程序返回一个值。定义中的各部分如下: 函数是被命名的:每个函数都
php操作redis哨兵模式,主从切换后自动获取master
本文将介绍如何使用PHP来连接redis哨兵模式。哨兵模式:大概的原理就是监听redis主库心跳包,如果心跳断开,则枚举一个从库推举成为新的主库,防止redis宕机不能使用。为了增强redis的性能,防止其挂掉,引用redis哨兵监控redis集群是个不错的选择。下面三步简单记录php连接redis哨兵。 第一步、获取哨兵模式连接redis句柄对象/
PHP 微信公众号消息加解密
公众号配置根据提示设置即可:【图中信息均为无意义数据,仅供参考。注意服务器地址需可接收 GET/POST 两种请求】 AESKey 直接点一下随机生成即可,Token 可以生成一个 UUID 再把 UUID 进行 MD5 一次即可。 接收关注事件消息示例 请求参数校验这一步根据项目情况,可供参考:(Lumen 框架)php$valida
Lumen 中对 Dingo API 异常接管并自定义响应结果
场景描述比如我们需要对 API 限流抛出的异常进行接管,并重写响应消息,首先应用中间件:phpuse Dingo\Api\Routing\Router;$apigroup( 'middleware' 'api.throttle', // 限流中间件 'expires' 1, // 时间范围,单位“分” 'lim
Bugku新平台——Web-wp
写在前面 Bugku新平台真不错,以前老平台的题 ak 了一直没有总结 wp ,这回重新打一遍写个 wp(水篇博客) web1F12查看源码得到flag web2F12修改前端JS对输入长度的限制 web3老萌新题了,但是不知道为什么打印两个flag出来php$what$GET['what'];echo $what;if($what'flag')echo '
Vue 3.0 有哪些新特性值得我们提前了解
一、迎接 Vue 3.0 1\. 简介在这里插入图片描述Vue.js 作者兼核心开发者尤雨溪宣布 Vue 3.0 进入 Beta 阶段。 已合并所有计划内的 RFC 已实现所有被合并的 RFC Vue CLI 现在通过 vueclipluginvuenext 提供了实验性支持 2\. 新特性重点关注: 更快更省
dubbo网关演进之路
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 背景随着公司业务的飞速发展,基于php的模块化架构难以支持未来业务的发展: php模块化架远远落后于行业主流架构(微服务–云原生),而php生态的服务治理开源组件匮乏,研发投入过大 杭州php人才匮乏,导致新鲜血液招聘困难 基于php的多进程架构难以支撑