注册
登录

您现在的位置是:首页 > 学无止境

PHP8.1 正式发布,来看下有哪些新功能

木木彡82 2021-11-28 16:29:04 0人围观
PHP8.1 正式发布,来看下有哪些新功能

转载自:https://learnku.com/laravel/t/63073

PHP 8.1 已经在 2021 年 11 月 25 日 发布,在文章中,在本文中,我们将逐一介绍所有功能、性能改进、更改和弃用。


新特性

与每个版本一样,PHP8.1 添加了一些不错的新特性。新特性会在每年的更新中越来越多。


枚举 RFC

枚举将在 PHP 8.1 中开始支持!如果你不确定枚举可以用在哪里,你可以阅读 这篇文档。


枚举的加入将会是 PHP 的一个大进步,因此我十分期待 PHP 8.1 中的枚举。你可以查看下面的代码示例,以对枚举有一个快速的预览:


enum Status {

  case Pending;

  case Active;

  case Archived;

}

以下是它们的使用方式:


class Post

{

    public function __construct(

        private Status $status = Status::Pending;

    ) {}


    public function setStatus(Status $status): void

    {

        // …

    }

}


$post->setStatus(Status::Active);

你可以在 这篇文章 中找到如何使用枚举的深入分析。


Fibers RFC

Fibers — 又叫 "绿色线程" — 是管理并行性的低级机制。您可能不会直接在您的应用程序中使用它们,但框架和 ReactPHP 等框架将大量使用它们。


这里有一个使用 fibers 的简单例子:


$fiber = new Fiber(function (): void {

    $valueAfterResuming = Fiber::suspend('after suspending');


    // … 

});


$valueAfterSuspending = $fiber->start();


$fiber->resume('after resuming');

如果您想读取更多关于 fibers 的信息,它们能做什么,不能做什么,你可以阅读 这篇文章.


性能提升 PR

Dmitry Stogov 对 opcache 进行了一些改进,他称之为 「inheritance cache」。这个新特性允许在缓存中连接两个类,就像 PHP 7.4 中两个类的 预加载 一样。


得益于这个新特性,Dmitry 说会提升 5% 到 8% 的性能,这是 PHP 8.1 中一个很好的小细节。


关联数组解包 RFC

数组的解包操作已经在 PHP 7.4 中支持了,但是只在数值数组中好用。之前不支持关联数组解包的原因是,在合并重复的数组键的问题上未能达成一致意见。RFC 通过 使用类似于 array_merge 的规则解决了这个问题。


$array1 = ["a" => 1];


$array2 = ["b" => 2];


$array = ["a" => 0, ...$array1, ...$array2];


var_dump($array); // ["a" => 1, "b" => 2]

RFC 的初始值设定项中出现 new

此 RFC 允许您在函数定义中使用关键字 new 作为默认参数,也可以在属性参数等地方使用。


class MyController {

    public function __construct(

        private Logger $logger = new NullLogger(),

    ) {}

}

您可以在 [这篇专题文章](stitcher . io/blog/PHP-81-new-in-initializer) 中阅读关于此功能的所有内容。


只读的 rfc 属性

类属性可以标记为只读,这意味着它们只能写入一次。


class PostData {

    public function __construct(

        public readonly string $title,

        public readonly DateTimeImmutable $date,

    ) {}

}

初始化只读属性后,尝试更改该属性将导致错误:


$post = new Post('Title', /* … */);


$post->title = 'Other';


Error: Cannot modify readonly property Post::$title

如果您想深入了解有关只读属性的更多信息,可以阅读我的后续文章.


你想了解更多关于 PHP 8.1 吗?有 (PHP 8.1 之路)(https://road-to-php.com/)。在接下来的十天里,你每天会收到邮件覆盖新的 PHP 8.1 和退出功能;之后你会自动 unsubscribed 所以没有垃圾邮件或跟踪。(现在就订阅!)(road-to-php.com/)


一流的可调用语法 RFC

现在,您可以通过调用一个可调用对象并将其作为参数传递…,从该可调用对象生成闭包:


function foo(int $a, int $b) { /* … */ }


$foo = foo(...);


$foo(a: 1, b: 2);

RFC 中的纯交叉类型

您已经了解了 PHP 8.0 中的 Union 类型 , 和交叉类型是一个类似的功能。如果联合类型要求输入为给定类型之一,则交叉类型要求输入为所有指定类型。交叉类型在处理大量接口时特别有用:


function generateSlug(HasTitle&HasId $post) {

    return strtolower($post->getTitle()) . $post->getId();

}

如果你喜欢这种代码风格,你需要创建一个新的接口 Sluggable,并在 $post 中实现它,

If you like this style of programming, you'd need to create a new interface Sluggable and implement it in $post, 交叉类型解决了这种额外的开销。


新类型 never RFC

可以使用 never 类型指示函数将实际停止程序流。这可以通过抛出异常、调用退出或其他类似函数来实现。


never 类型可以用来表示整个程序在一个函数中终止了。可以通过抛出异常、调用 exit、或是其他类似的函数来实现。


function dd(mixed $input): never

{

    // 输出内容


    exit;

}

never 与 void 的不同之处是, void 表示程序还在继续运行。这似乎是一个新奇的功能,但实际上对于静态分析来说却是一个非常有用的功能。


新函数 array_is_list RFC

你可能偶尔需要处理类似这样的问题:确定数组的键是否从索引 0 开始按数字顺序排列。例如 json_ encode 需要决定将 json 转换为数组还是对象。


PHP 8.1 添加了一个内置函数来确定数组是否是具有这些语义的列表:


$list = ["a", "b", "c"];


array_is_list($list); // true


$notAList = [1 => "a", 2 => "b", 3 => "c"];


array_is_list($notAList); // false


$alsoNotAList = ["a" => "a", "b" => "b", "c" => "c"];


array_is_list($alsoNotAList); // false

RFC 的最终类常量

PHP 中的类常量可以在继承过程中被覆盖:


class Foo

{

    public const X = "foo";

}


class Bar extends Foo

{

    public const X = "bar";

}

从 PHP 8.1 开始,您可以将这样的常量标记为 final,以防止出现这种情况:


class Foo

{

    final public const X = "foo";

}


class Bar extends Foo

{

    public const X = "bar";

    Fatal error: Bar::X cannot override final constant Foo::X

}

RFC 的新函数 fsync

PHP 8.1 增加了 fsync 函数和 fdatync 函数,强制将文件更改同步到磁盘,并确保操作系统写缓冲区在返回前已刷新。


$file = fopen("sample.txt", "w");


fwrite($file, "Some content");


if (fsync($file)) {

    echo "File has been successfully persisted to disk.";

}


fclose($file);

因为磁盘同步是一个文件系统操作,所以 fsync 函数将只对普通文件流起作用。尝试同步非文件流将发出警告。


显式八进制整数文字表示法:RFC

您现在可以使用 0o 和 0O 来表示八进制数。前面用 0 作为数字前缀的表示法仍然有效。


016 === 0o16; // true

016 === 0O16; // true

突破性变化

虽然 PHP8.1 是一个小版本,但在技术上可能会有一些突破性的变化,也会有一些不赞成的意见。让我们逐一讨论。


RFC 的内部方法返回类型

在升级到 PHP 8.1 时,您可能会遇到此弃用通知:


返回类型应该与IteratorAggregate::getIterator():Traversable兼容,

或者应该使用 #[ReturnTypeWillChange] 属性暂时隐藏通知

你可能注意到了,这个错误信息会在使用 phpunit/phpunit、symfony/finder 和其他流行的开源包中出现。实际是因为内部函数开始使用正确的返回类型。如果想要从标准库(如 IteratorAggregate)中继承一个类,这时还需要添加返回类型。


修复方法很简单:如果第三方软件包中出现错误,请更新软件包的代码(其中大多数已在最新版本中修复)。如果代码中出现错误,您可以添加 ReturnTypeWillChange 属性,在 PHP 9.0 之前抑制这些错误。下面是一个类扩展 DateTime 的示例:


class MyDateTime extends DateTime

{

    /**

     * @return DateTime|false

     */

    #[ReturnTypeWillChange]

    public function modify(string $modifier) 

    { 

        return false; 

    }

}

或者你可以添加返回类型:


class MyDateTime extends DateTime

{

    public function modify(string $modifier): DateTime|false 

    { 

        return false; 

    }

}

限制 $GLOBALS 的使用 RFC

一个对于 $GLOBALS 使用方式的小更改将对所有阵列操作的性能产生重大影响。Nikita 在 RFC 中很好地解释了问题和解决方案。这个变动意味着 $GLOBALS 不会在一些边缘情况下做出什么事情了。 $GLOBALS 不再支持整体写入。下面的做法都将报错。


$GLOBALS = [];

$GLOBALS += [];

$GLOBALS =& $x;

$x =& $GLOBALS;

unset($GLOBALS);

引用调用 $GLOBALS 会导致一个运行时错误


by_ref($GLOBALS);

Nikita 分析了 Packagist 上排名前 2000 的包,只发现了 23 个会受到这一变化的影响。我们可以得出结论,这种技术突破性变化的影响将很小,这就是为什么内部决定在 PHP 8.1 中添加它。请记住,考虑到这一变化对我们代码中的每个地方都有积极的性能影响,我们中的大多数人都将从这一更改中获益。


资源到对象的迁移

这些变化是将所有资源转换为专用对象的长期愿景的一部分。你可以在这里了解更多。


带有 finfo 对象的 Fileinfo 函数


finfo_file、finfo_open 等函数用于接受和返回资源。从 PHP8.1 开始,它们可以使用所有的 finfo对象。


 具有 IMAPConnection 对象的 IMAP 函数


就像 fileinfo 的改变一样,IMAP 函数如 imap_body 和 imap_open 不再使用资源


不推荐将 null 传递给内部函数 rfc 的不可为空的参数

这个更改很简单:内部函数当前接受不可为空的参数为 null,这个 RFC 反对这种行为。例如,目前这是可能的:


str_contains("string", null);

在 PHP 8.1 中,这些类型的错误将抛出一个弃用警告,在 PHP 9 中,它们将被转换为类型错误。


自动复活 false rfc

来自 RFC:


PHP 本身允许自动复活 (根据 falsey 值自动创建数组)。这个特性非常有用,在许多 PHP 项目中都有使用,特别是在变量未定义的情况下。但是,有一点奇怪,允许从 false 和 null 值创建数组。


您可以在 RFC 页面上阅读详细信息。总之,不推荐使用这种行为:


$array = false;


$array[] = 2;


Automatic conversion of false to array is deprecated

其他小变化

对于每一个发布版本,都会有一些非常小的语言变化。所有这些都被列在 GitHub 的升级指南和弃用的 RFC RFC 中,如果你想知道每一个小细节,一定要去看看。


以下是一些最重要的变化:


MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH 最大长度不再有效果


MYSQLI_STORE_RESULT_COPY_DATA 不再有效


PDO::ATTR_STRINGIFY_FETCHES 现在也可以用布尔值了


当使用模拟准备语句时,PDO MySQL 和 Sqlite 结果集中的整数和浮点数将使用本地 PHP 类型而不是字符串返回


像 htmlspecialchars 和 htmlentities 这样的函数在默认情况下也会转换为 ' ; 格式不正确的 utf-8 也会被 Unicode 字符替换,而不是产生一个空字符串


hash、 hash_file 和 hash _ init 有一个额外的参数添加到它们中,称为 $options,它的默认值为 [] ,因此不会影响代码


MurmurHash3 和 xxHash 新的支持

文章评论

  • 登录后评论

点击排行