2019-05-19 PHP7各个版本新增特性 文章目录 1. 7.0.x1.1. 新特性1.1.1. null合并运算符1.1.2. 太空船操作符1.1.3. 新增整数除法函数intdiv()1.1.4. 标量参数类型声明1.1.5. 返回值类型声明1.1.6. 通过define()定义常量数组1.1.7. 匿名类1.1.8. Closure::call()1.2. 变更1.2.1. 错误和异常处理1.2.2. foreach变化1.2.2.1. 循环时候不在改变内部数组指针1.2.2.2. 通过引用遍历时候,能够动态更该遍历1.2.3. 性能的提升与内存使用减少2. 7.1.x2.1. 新特性2.1.1. 可为空(Nullable)类型2.1.2. void类型返回值类型2.1.3. iterable类型2.1.4. 数组解构赋值2.1.5. list()增强支持键名2.1.6. 支持捕获多个类型2.1.7. 支持负的字符串偏移量2.1.8. is_iterable()验证变量是否是可迭代类型3. 7.2.x3.1. 对象类型3.2. 参数类型拓展4. 7.3.x4.1. json_decode()抛出异常4.2. is_countable()验证变量是否可以计数类型4.3. array_key_first(), array_key_last()获取数组第一个和最后一个key4.4. list支持引用赋值5. 参考 PHP从5.6 跳过6直接来到7,带来新的语言特性,更带来性能很大飞越。根据w3techs统计截止截止2019年5月18月有79%网站使用PHP做为服务端开发语言,这些网站使用的PHP版本统计如下: 其中PHP 5 和 PHP 7细化分布下: 这里我们不探讨性能提升方面,只是看看PHP7带来了哪些语言上的新特性。下面是PHP7各个版本新增特性详细说明: 7.0.x 新特性 null合并运算符 PHP 5中我们常使用isset和三目运算符来判断变量是否存在,PHP 7开始可以使null合并运算符(??),如果变量存在且值不为NULL,则返回自身的值,否则返回它的第二个操作数。 123456789<?php$x = NULL;$y = NULL;$z = 3;var_dump($x ?? $y ?? $z); // int(3) $x = ["c" => "meaningful_value"];var_dump($x["a"] ?? $x["b"] ?? $x["c"]); // string(16) "meaningful_value" 太空船操作符 太空船操作符(<=>),用于两个表达式,当a小于、等于或者大于a小于、等于或者大于a小于、等于或者大于b时,分别返回-1、0、1 12345678910$array = [1, 2, 3, 4, 6];// PHP 5usort($array, function ($a, $b) { return ($a < $b) ? -1 : ($a = $b ? 0 : 1);});// PHP 7usort($array, function ($a, $b) { return $a <=> $b; }); 新增整数除法函数intdiv() intdiv用于整数的除法运算 123<?phpvar_dump(intdiv(10, 3)); // int(3) 标量参数类型声明 PHP 5也支持参数类型声明,但它只支持复合变量类型声明,比如类或数组声明。PHP 7 开始之后支持int,bool等标量类型声明了。具体支持支持类型如下: 类型 描述 最低 PHP版本 class/interface name 参数必须是类或者接口的一个实例 PHP 5.0.0 self 参数必须是当前类的实例 PHP 5.0.0 array 参数必须是一个数组 PHP 5.1.0 callable 参数必须是一个可回调类型 PHP 5.4.0 bool 参数必须布尔类型 PHP 7.0.0 float 参数必须是浮点类型 PHP 7.0.0 int 参数必须是整数类型 PHP 7.0.0 string 参数必须是字符串类型 PHP 7.0.0 返回值类型声明 返回类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同, 见上表 1234567891011<?phpinterface A { static function make(): A;}class B implements A { static function make(): A { return new B(); }} 通过define()定义常量数组 PHP 5.6中只能通过const定义数组常量,现在可以通过define()来定以 12345678<?phpdefine('ANIMALS', [ 'dog', 'cat', 'bird']);echo ANIMALS[1]; // 输出 "cat" 匿名类 PHP 7 开始支持同 new class 来实例化一个匿名类, 12345678910<?php$di = new DI();$di->setLogger(new class { public function log(string $msg) { echo $msg; } }}) Closure::call() Closure::call() 用于绑定一个方法到对象上闭包并调用它,并有着更好的性能 123<?php 变更 错误和异常处理 PHP 7 起大部分错误可以被作为Error异常抛出。PHP 5 使用错误报告等来处理错误, 可参看PHP错误与异常处理详解(一)。 PHP 7 抛出的Error 可以通过catch(Error $e) {}来捕获或注册异常处理函数set_exception_handler来捕获。所有异常和错误类都实现了Throwalble接口。 Error的层次接口结构: Throwable Error ArithmeticError DivisionByZeroError DivisionByZeroError AssertionError ParseError TypeError ArgumentCountError Exception ClosedGeneratorException DOMException ErrorException IntlException LogicException BadFunctionCallException BadMethodCallException DomainException InvalidArgumentException LengthException OutOfRangeException PharException ReflectionException RuntimeException OutOfBoundsException OverflowException PDOException RangeException UnderflowException UnexpectedValueException set_exception_handler()接收的对象不一定是Exception对象,有可能是Error对象 123456789// PHP 5 时代代码func handler(Excetion $e) { ... } // 如果此时接受到Error对象,将会导致fatal errorset_exception_handler('handler')// 兼容PHP 5 和 7function handler($e) {...}// 仅支持 PHP 7function handler(Throwalbe $e) { ... } foreach变化 循环时候不在改变内部数组指针 PHP 7之前,当数组通过foreach 迭代时候,数组指针会移动。 123456<?php$array = [0, 1, 2];foreach ($array as &$val) {}var_dump(current($array); // php 5 输出 bool(false); php 7 输出int(1) 通过引用遍历时候,能够动态更该遍历 123456<?php$array = [0];foreach ($array as &$val) { // 注意此处一定是引用遍历,否则没有效果 var_dump($val); $array[1] = 1;} PHP 5 输出: 1int(0) PHP 7 输出: 12int(0)int(1) 注意PHP 5 和 PHP 7最后的数组$array都会多一个元素1 123<?php$array = [0, 1]; 更多PHP 7.0.x 变更与新特性见从PHP 5.6.x 移植到 PHP 7.0.x 性能的提升与内存使用减少 PHP 7速度相比 5.6提升了2倍 内存使用显著下降 7.1.x 新特性 可为空(Nullable)类型 参数类型和返回值类型支持可为空类型。当在类型前面加一个问,传入的参数或函数返回值要么是该类型,要么是null 1234567891011121314151617181920212223<?phpfunction answer(): ?int { return null; //ok}function answer(): ?int { return 42; // ok}function answer(): ?int { return new stdclass(); // error}function say(?string $msg) { if ($msg) { echo $msg; }}say('hello'); // ok -- prints hellosay(null); // ok -- does not printsay(); // error -- missing parametersay(new stdclass); //error -- bad type void类型返回值类型 一个新的返回值类型void被引入。 返回值声明为 void 类型的方法要么干脆省去 return 语句,要么使用一个空的 return 语句。 对于 void 函数来说,NULL 不是一个合法的返回值,试图去获取void方法的返回值会得到NULL 123456789101112131415<?phpfunction swap(&$left, &$right) : void{ if ($left === $right) { return; } $tmp = $left; $left = $right; $right = $tmp;}$a = 1;$b = 2;var_dump(swap($a, $b), $a, $b); 上面程序会输出: 123nullint(2)int(1) iterable类型 iterable类型可用于参数类型提示,或者返回值类型提示,表明参数或返回值是一个数组或者实现了Traversable接口的对象。 iterable类型可用于foreach循环。 123456<?phpfunction foo(iterable $iterable) { foreach ($iterable as $value) { // ... }} 数组解构赋值 结构赋值实现list()类似功能 123456789101112131415161718<?php$array = [1, 2, 3];[$a, $b, $c] = $array; // 效果跟list($a, $b, $c) = $array; 一样// 支持键名$array = ['a' => 1, 'b' => 2, 'c' => 3];["a" => $a, "b" => $b, "c" => $c] = $array;$data = [ [1, 'Tom'], [2, 'Fred'],];foreach ($data as list($id, $name)) {}foreach ($data as [$id, $name]) {} list()增强支持键名 123<?php$array = ['a' => 1, 'b' => 2, 'c' => 3];list("a" => $a, "b" => $b, "c" => $c) = $array; 支持捕获多个类型 123456789<?phptry { // Some code...} catch (ExceptionType1 | ExceptionType2 $e) { // Code to handle the exception} catch (\Exception $e) { // ...} 支持负的字符串偏移量 一个负数的偏移量表明从字符串结尾开始的偏移量 123<?phpvar_dump("abcdef"[-2]);var_dump(strpos("aabbcc", "b", -3)); 上面程序将会输出 12string (1) "e"int(3) is_iterable()验证变量是否是可迭代类型 is_iterable用来验证变量是否是iterable伪类类型 123456<?phpvar_dump(is_iterable([1, 2, 3])); // bool(true)var_dump(is_iterable(new ArrayIterator([1, 2, 3]))); // bool(true)var_dump(is_iterable((function () { yield 1; })())); // bool(true)var_dump(is_iterable(1)); // bool(false)var_dump(is_iterable(new stdClass())); // bool(false) 7.2.x 对象类型 对象类型用于输入参数和函数返回值都是任何对象乐西 12345678<?phpfunction test(object $obj) : object{ return new SplQueue();}test(new StdClass()); 参数类型拓展 重写方法和接口实现的参数类型可以使任意类型,即使父类方法指定一个固定的参数类型 1234567891011<?phpinterface A{ public function Test(array $input);}class B implements A{ public function Test($input){} // type omitted for $input} 更多新特性与变更见从PHP 7.1.x 移植到 PHP 7.2.x 7.3.x json_decode()抛出异常 json_decode()第二个参数传入JSON_THROW_ON_ERROR,那么当json解析失败是,会抛出JsonException异常 7.2之前(含7.2)的获取json解析错误使用如下方法: 12345<?phpjson_decode("{");json_last_error() === JSON_ERROR_NONE // 结果是falseecho json_last_error_msg() // 输出 "Syntax error" 7.3起我们可以捕获json处理异常了: 1234567891011<?phpuse JsonException; try { $json = json_encode("{", JSON_THROW_ON_ERROR); return base64_encode($json);} catch (JsonException $e) { echo $e->getMessage(); // 类似json_last_error_msg() echo $e->getCode(); // 类似 json_last_error()} is_countable()验证变量是否可以计数类型 12345678910<?php// 7.3之前if (is_array($foo) || $foo instanceof Countable) { // $foo is countable}// 7.3开始if (is_countable($foo)) { // $foo is countable} array_key_first(), array_key_last()获取数组第一个和最后一个key 1234<?php$firstKey = array_key_first($array);$lastKey = array_key_last($array); list支持引用赋值 1234<?php$array = [1, 2];list($a, &$b) = $array; 等效于: 12345<?php$array = [1, 2];$a = $array[0];$b =& $array[1]; 参考 PHP 官方文档之各版本迁移 Evolution of PHP — v5.6 to v8.0 Usage statistics and market share of PHP for websites The PHP Benchmark How Fast is WordPress with PHP-FPM 7 Compare to 5? Newer Supervisor快速使用指南 Older 记一次inode使用100%导致文件无法创建问题