PHP7.4 新特性

Typed properties

  • 现在类的属性支持类型声明了:

    class User {
        public int $id;
    
        public string $name;
    }
    
  • 注:设置属性 $id$name 的值时必须要指定类型,否则会报错:
    PHP Fatal error: Uncaught TypeError: Typed property User::$id must be int, string used
  • 注:访问属性之前必须要先初始化,否则会报错:
    • PHP Fatal error: Uncaught Error: Typed property User::$id must not be accessed before initialization

Arrow functions

  • 箭头函数是简化版语法的匿名函数,它们功能相同,只有一个区别:箭头函数可以直接使用父作用域内的变量。

  • 基本语法:fn (argument_list) => expr

  • 匿名函数 vs 箭头函数

    $y = 1;
    
    $fn1 = fn($x) => $x + $y;
    // 相当于 use $y:
    $fn2 = function ($x) use ($y) {
        return $x + $y;
    };
    
  • 箭头函数支持任意形式的函数签名(包括参数类型、参数默认值、返回值类型、变长参数)以及按引用传递和返回。

    <?php
    
    fn(array $x) => $x;
    static fn(): int => $x;
    fn($x = 42) => $x;
    fn(&$x) => $x;
    fn&($x) => $x;
    fn($x, ...$rest) => $rest;
    
  • 因为箭头函数「按值绑定」使用变量,相当于 use ($x),所以函数内不能修改外部的变量。

    <?php
    
    $x = 1;
    $fn = fn() => $x++;
    $fn();
    echo $x; // 1
    

return type covariance and argument type contravariance(协变返回和逆变参数)

  • Covariant (协变):类型从通用到具体

  • Contravariant (逆变): 类型从具体到通用

    // 协变返回
    <?php
    class ParentType {}
    class ChildType extends ParentType {}
    
    class A
    {
        public function covariantReturnTypes(): ParentType
        { return new ParentType(); }
    }
    
    class B extends A
    {
        public function covariantReturnTypes(): ChildType
        { return new ChildType(); }
    }
    
    // 逆变参数
    class C
    {
        public function contraVariantArguments(ChildType $type)
        { return $type; }
    }
    
    class D extends C
    {
        public function contraVariantArguments(ParentType $type)
        { return $type; }
    }
    

Null coalescing assignment operator(NULL 合并运算符)

<?php
$array['key'] ??= 1;
// 等于下面
$array['key'] = $array['key'] ?? 1;
// 或
if (!isset($array['key'])) {
    $array['key'] = 1;
}

var_dump($array);

Unpacking inside arrays(数组内支持展开运算符)

  • 语法:$arr = [...$args];
<?php
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
  • 注:仅支持数字索引的数组

  • 展开运算符的一个优点是它支持任何可遍历的对象,如生成器:

    function generator() {
      for ($i = 3; $i <= 5; $i++) {
          yield $i;
      }
    }
    $arr1 = [0, 1, 2, ...generator()];
    
  • 注:不支持引用传递的方式:

    <?php
    $arr2 = ['red', 'green', 'blue'];
    $arr3 = [...&$arr2]; // 报错:PHP Parse error:  syntax error, unexpected '&'
    
  • 但是支持包含引用值的数组:

    $red = 'red';
    $arr4 = [&red, 'green', 'blue'];
    $arr5 = ['white', ...$arr1, 'black'];
    

Numeric literal separator(数字字面量分隔符)

  • 支持数字中的下划线来可视化地分隔数字(可以提高代码的可读性)
6.674_083e-11; // float

299_792_458;   // decimal

0xCAFE_F00D;   // hexadecimal

0b0101_1111;   // binary

0137_041;      // octal
  • 注:下划线必须直接位于两个数字之间,以下是不合法的示例:
// PHP Parse error:  syntax error, unexpected '_' (T_STRING)

100_;       // trailing

1__1;       // next to underscore

1_.0; 1._0; // next to decimal point

0x_123;     // next to x

0b_101;     // next to b

1_e2; 1e_2; // next to e

Weak references(弱引用)

  • 引入了弱引用类型:WeakReference,这样开发者就可以保留对对象的引用,而这不会阻止对象本身被破坏。
<?php
$object = new stdClass;
$weakRef = WeakReference::create($object);

var_dump($weakRef->get());
unset($object);
var_dump($weakRef->get());

// 第一次 var_dump
object(stdClass)#1 (0) {}

// 第二次 var_dump,当 object 被销毁的时候,并不会抛出致命错误
NULL

Allow exceptions from __toString()

现在允许 __toString() 里面抛出异常了,而之前会抛出一个 fatal error。

OPcache 支持预加载

服务器启动时 – 在运行任何应用程序代码之前 – 我们可以将一组 PHP 文件加载到内存中 – 并使得这些预加载的内容,在后续的所有请求中 “永久可用”。这些文件中定义的所有函数和类在请求时,就可以开箱即用,与内置函数相同。

预加载由 php.ini 的 opcache.preload 进行控制。这个参数指定在服务器启动时编译和执行的 PHP 脚本。

opcache.preload=preload.php

在这个文件里面用 includerequire 等方法包含的文件名都会被预加载。

Custom object serialization(自定义对象序列化函数)

  • 新增了两个魔术方法,用于序列化和反序列化对象,并且替代了 Serializable 接口,后者在未来会被弃用。
public function __serialize(): array;

public function __unserialize(array $data): void;

参考