目录

PHP74 新特性

整理一下 PHP-7.4.0 提供的一些改进和新特性。

有类型的类属性

类属性现在支持类型声明。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

class User
{
    public int $id;
    public string $name;
}

$user = new User();
$user->id = '123';
$user->name = 123;

var_dump($user->id, $user->name);

// 结果
int(123)
string(3) "123"

箭头函数

箭头函数为使用隐式按值范围绑定定义函数提供了一种简写语法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php

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

var_dump($nums);

// 结果
array(4) {
  [0]=>
  int(10)
  [1]=>
  int(20)
  [2]=>
  int(30)
  [3]=>
  int(40)
}

有限返回类型协变和参数类型逆变

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php

class A
{
}

class B extends A
{
}

class Producer
{
    public function method(): A
    {
        echo __METHOD__, PHP_EOL;

        return new A();
    }
}

class ChildProducer extends Producer
{
    public function method(): B
    {
        echo __METHOD__, PHP_EOL;

        return new B();
    }
}

$producer = new Producer();
$childProducer = new ChildProducer();

if ($producer->method() instanceof A) {
    var_dump('我特么就返回 A 的实例');
}
if ($childProducer->method() instanceof B) {
    var_dump('我特么就返回 B 的实例');
}

// 结果
Producer::method
string(30) "我特么就返回 A 的实例"
ChildProducer::method
string(30) "我特么就返回 B 的实例"

NULL 合并运算符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php

function defaultValue(): string
{
    return '';
}

$array = $_REQUEST;

// PHP74 之前

if (! isset($array['key'])) {
    $array['key'] = defaultValue();
}

// PHP74 开始
$array['key'] ??= defaultValue();

// 虽然以下代码也可以,但是本人强烈反对这样写,不要问我为什么。代码块我总是用 {} 包起来
if (! isset($array['key'])) $array['key'] = defaultValue();

在数组内部展开元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php

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

var_dump($fruits);

// 结果
array(5) {
  [0]=>
  string(6) "banana"
  [1]=>
  string(6) "orange"
  [2]=>
  string(5) "apple"
  [3]=>
  string(4) "pear"
  [4]=>
  string(10) "watermelon"
}

数字字面量分隔符

人眼并未针对快速解析长数字序列进行优化。 因此,缺少视觉分隔符会使读取和调试代码花费更长的时间,并可能导致意外错误。

所以 数字字面量分隔符 就是解决人眼快速识别而做出的优化,你看,代码的的确确是机器去执行的,但更重要的是 可读可写可赏可赞 😂。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
6.674_083e-11; // float
299_792_458;   // decimal
0xCAFE_F00D;   // hexadecimal
0b0101_1111;   // binary
0137_041;      // octal

1_000_000; // versus 1000000
3.141_592; // versus 3.141592
0x02_56_12; // versus 0x025612
0b0010_1101; // versus 0b00101101
0267_3432; // versus 02673432
1_123.456_7e2 // versus 1123.4567e2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php

usleep(345126); // without separator

usleep(345_126); // with separator

if (12345678989876 === 12345678998876) {
    echo 'Equal';
} else {
    echo 'Unequal';
}

echo PHP_EOL;

if (12_345_678_989_876 === 12_345_678_998_876) {
    echo 'Equal';
} else {
    echo 'Unequal';
}

弱引用

允许来自 toString() 的异常

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php

class CustomException extends \Exception
{
}

class Foo
{
    public function __toString()
    {
        throw new CustomException('Oops!');
    }
}

$foo = new Foo();

try {
    var_dump((string) $foo);
} catch (CustomException $e) {
    var_dump($e);
}

// 结果

// PHP56
PHP Fatal error:  Method Foo::__toString() must not throw an exception in /path/to/User.php on line 0

// PHP73
PHP Fatal error:  Method Foo::__toString() must not throw an exception, caught CustomException: Oops! in /path/to/a.php on line 0

// PHP74
object(CustomException)#2 (7) {
  ["message":protected]=>
  string(5) "Oops!"
  ["string":"Exception":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(47) "/Users/xxx/Codes/example/untitled/User.php"
  ["line":protected]=>
  int(11)
  ["trace":"Exception":private]=>
  array(1) {
    [0]=>
    array(6) {
      ["file"]=>
      string(47) "/Users/xxx/Codes/example/untitled/User.php"
      ["line"]=>
      int(18)
      ["function"]=>
      string(10) "__toString"
      ["class"]=>
      string(3) "Foo"
      ["type"]=>
      string(2) "->"
      ["args"]=>
      array(0) {
      }
    }
  }
  ["previous":"Exception":private]=>
  NULL
}

Opcache 预加载

opcache.preload string:指定要在服务器启动时期进行编译和缓存的 PHP 脚本文件,这些文件也可能通过 include 或者 opcache_compile_file() 函数来预加载其他文件。所有这些文件中包含的实体,包括函数、类等,在服务器启动的时候就被加载和缓存,对于用户代码来讲是『开箱可用』的。

一些不推荐

Deprecated Features

从核心中移除的扩展

Removed Extensions