PHP 7.4.0发布!一块儿看看有哪些新特性

PHP 7.4.0 发布了,此版本标志着 PHP 7 系列的第四次特性更新。php

看了英文手册后,发现其进行了许多改进,并带来了一些新特性,如今将这些新特性您:laravel

 

1.Typed Properties 类型属性数组

类属性如今支持类型声明,如下示例将强制 $User-> id 只能分配 int 值,而 $User-> name 只能分配 string 值。缓存

<?php

class User {

    public int $id;

    public string $name;

}

?>

● 它们自PHP 7.4起可用。服务器

● 它们只在类中可用,而且须要访问修饰符:public、protected、private、var。闭包

● 除了void和callable以外,全部类型都是容许的。app

PHP是咱们喜欢和讨厌的一种动态语言,它将强制类型转换作的太好,有时也会引发副作用。假设您在指望整数的地方传递了一个字符串,PHP将尝试自动转换该字符串:composer

class Bar

{

    public int $i;

}

$bar = new Bar;

$bar->i = '1'; // 1

若是不喜欢这种行为,能够经过声明严格类型来禁用它:框架

declare(strict_types=1);
$bar = new Bar; $bar->i = '1'; // 1
 Fatal error: Uncaught TypeError: Typed property Bar::$i must be int, string used

 

2.Arrow Functions 箭头函数ide

箭头函数提供了用于定义具备隐式按值做用域绑定的函数的简写语法。

<?php

$factor = 10;

$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);

// $nums = array(10, 20, 30, 40);

?>

● 自PHP 7.4起可用

● 他们以fn关键字开头

● 它们只能有一个表达式,即return语句

● 不容许return关键字

● 参数和返回类型能够是类型提示

您没看错:短闭包只能有一个表达式。这意味着您不能包含多行。

理由以下:

简短闭包的目标是减小冗长。fn固然在全部状况下都比function短。然而,若是您处理的是多行函数,那么使用短闭包所得到的好处就更少。

毕竟,按照定义,多行闭包已经更加冗长;所以可以跳过两个关键字(function和return)不会有太大的区别。

 

3.Limited Return Type Covariance and Argument Type Contravariance 有限返回类型协变与参数类型逆变

仅当使用自动加载时,才提供彻底协变/逆变支持。在单个文件中,只能使用非循环类型引用,由于全部类在被引用以前都必须可用。

<?php

class A {}

class B extends A {}

class Producer {

    public function method(): A {}

}

class ChildProducer extends Producer {

    public function method(): B {}

}

?>

 

4.Unpacking Inside Arrays 打包内部数组

<?php

$parts = ['apple', 'pear'];

$fruits = ['banana', 'orange', ...$parts, 'watermelon'];

// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

?>

 

5.Numeric Literal Separator 数值文字分隔符

数字文字能够在数字之间包含下划线。

<?php

6.674_083e-11; // float

299_792_458;   // decimal

0xCAFE_F00D;   // hexadecimal

0b0101_1111;   // binary

?>

限制

惟一的限制是数字文字中的每一个下划线必须直接位于两个数字之间。这条规则意味着下面的用法都不是有效的数字文字:

_100; 

100_;       

1__1;       

1_.0; 1._0; 

0x_123;     

0b_101;     

1_e2; 1e_2; 

PHP功能不受影响

在数字文字的数字之间添加下划线不会改变其值。下划线在词法分析阶段被删除,所以运行时不受影响。

var_dump(1_000_000); // int(1000000)

 

6.Weak References 弱引用

弱引用能够保留对对象的引用,不会阻止对象被销毁。

弱引用容许保留对对象的引用,而该对象不会阻止对象被销毁;它们对于实现相似缓存的结构很是有用。

原则上,弱引用对象并不复杂,只须要(ab)使用Zend或下面的层,由于咱们不直接支持它。

final class WeakReference {

    public static function create(object $object) : WeakReference;
  
    public function get() : ?object;

}

 

7.Allow Exceptions from __toString() 容许从 __toString() 抛出异常

如今容许从 __toString() 引起异常,以往这会致使致命错误,字符串转换中现有的可恢复致命错误已转换为 Error 异常。

7.4之前禁止从__toString()抛出异常,若是__toString()异常,将致使致命错误。

从技术角度来看,这种限制最终是无效的,由于字符串转换期间的异常仍然能够由将可恢复错误转换为异常的错误处理程序触发:

set_error_handler(function() {

    throw new Exception();

});

try {

    (string) new stdClass;

} catch (Exception $e) {

    echo "(string) threw an exception...\n";

}

另外,将“不能转换为字符串”和“__toString()必须返回一个字符串值”可恢复的致命错误转换为正确的错误异常,这与PHP 7中创建的错误策略一致。

 

8.Opcache Preloading Opcache 预加载

新增 Opcache 预加载支持。

在PHP 7.4中,添加了对预加载的支持,这是一个能够显著提升代码性能的特性。

简而言之,这是它的工做方式:

● 为了预加载文件,您须要编写一个自定义PHP脚本

● 该脚本在服务器启动时执行一次

● 全部预加载的文件在内存中均可用于全部请求

● 在从新启动服务器以前,对预加载文件所作的更改不会产生任何影响

虽然预加载是创建在opcache之上的,但它并非彻底同样的。Opcache将获取您的PHP源文件,将其编译为“ opcodes”,而后将这些编译后的文件存储在磁盘上

您能够将操做码看做是代码的底层表示,在运行时很容易解释。所以,opcache会跳过源文件和PHP解释器在运行时实际须要之间的转换步骤。巨大的胜利!

但咱们还有更多的收获。Opcached文件不知道其余文件。若是类A是从类B扩展而来的,那么仍然须要在运行时将它们连接在一块儿。此外,opcache执行检查以查看源文件是否被修改,并将基于此使其缓存失效。

所以,这就是预加载发挥做用的地方:它不只将源文件编译为操做码,并且还将相关的类、特征和接口连接在一块儿。而后,它将这个“已编译”的可运行代码blob(即:PHP解释器可使用的代码)保存在内存中

如今,当请求到达服务器时,它可使用已经加载到内存中的部分代码库,而不会产生任何开销。

为了进行预加载,开发人员必须告知服务器要加载哪些文件。这是用一个简单的PHP脚本完成的,确实没有什么困难。

规则很简单:

● 您提供一个预加载脚本,并使用opcache.preload命令将其连接到您的php.ini文件中。

● 您要预加载的每一个PHP文件都应该传递到opcache_compile_file(),或者在预加载脚本中只须要一次。

假设您想要预加载一个框架,例如Laravel。您的脚本必须遍历vendor/laravel目录中的全部PHP文件,并将它们一个接一个地添加。

在php.ini中:

opcache.preload=/path/to/project/preload.php

这是一个虚拟的实现:

$files = /* 要预加载的文件数组 */;

foreach ($files as $file) {

    opcache_compile_file($file);

}

有一个警告!为了预加载文件,还必须预加载它们的依赖项(接口,特征和父类)

若是类依赖项有任何问题,则会在服务器启动时通知您:

Can't preload unlinked class

Illuminate\Database\Query\JoinClause: 

Unknown parent 

Illuminate\Database\Query\Builder

这不是一个致命的问题,您的服务器能够正常工做。但你不会获得全部你想要的预加载文件。

幸运的是,还有一种确保连接文件也被加载的方法:您可使用require_once代替opcache_compile_file,让已注册的autoloader(多是composer的)负责其他的工做。

$files = /* 要预加载的文件数组 */;

foreach ($files as $file) {

    require_once($file);

}

还有一些须要注意的地方。例如,若是您试图预加载Laravel,那么框架中的一些类依赖于其余尚不存在的类。例如,文件系统缓存类\ lighting \ filesystem \ cache依赖于\League\Flysystem\Cached\Storage\AbstractCache,若是您从未使用过文件系统缓存,则可能没法将其安装到您的项目中。

#有效吗?

这固然是最重要的问题:全部文件都正确加载了吗?您能够简单地经过从新启动服务器来测试它,而后将opcache_get_status()的输出转储到PHP脚本中。您将看到它有一个名为preload_statistics的键,它将列出全部预加载的函数、类和脚本;以及预加载文件消耗的内存。

#性能

如今到最重要的问题:预加载真的能提升性能吗?

答案是确定的:我进行了一些基准测试。

有趣的是,您能够决定仅预加载代码库中常用的类。基准测试显示,只加载大约100个热门类,实际上能够得到比预加载全部类更好的性能收益。预加载所有类,性能提高13%,而预加载热门类,则提高有17%。

固然,应该预加载哪些类取决于您的项目。明智的作法是在开始时尽量多地预加载。

此外还有一些弃用,以及从核心中删除一些扩展,详情查看英文原版手册:

https://www.php.net/manual/zh/migration74.new-features.php

相关文章
相关标签/搜索