PHP 7.1新特性的汇总介绍


Posted in PHP onDecember 16, 2016

一、可空类型

可空类型主要用于参数类型声明和函数返回值声明。

主要的两种形式如下:

<?php
function answer(): ?int {
 return null; //ok
}

function answer(): ?int {
 return 42; // ok
}

function say(?string $msg) {
 if ($msg) {
 echo $msg;
 }
}

从例子很容易理解,所指的就是通过 ? 的形式表明函数参数或者返回值的类型要么为指定类型,要么为 null。

此方法也可用于接口函数的定义:

<?php
interface Fooable {
 function foo(?Fooable $f);
}

但有一个需要注意的地方:如果函数本身定义了参数类型并且没有默认值,即使是可空的,也不能省略,否则会触发错误。如下:

<?php
function foo_nullable(?Bar $bar) {}

foo_nullable(new Bar); // 可行
foo_nullable(null); // 可行
foo_nullable(); // 不可行

但是如果以上函数的参数定义为 ?Bar $bar = null 的形式,则第三种写法也是可行的。因为 = null 实际上相当于 ? 的超集,对于可空类型的参数,可以设定 null 为默认值。

二、list 的方括号简写

我们知道在 PHP5.4 之前只能通过 array() 来定义数组,5.4之后添加了 [] 的简化写法(省略了5个字符还是很实在的)。

<?php
// 5.4 之前
$array = array(1, 2, 3);
$array = array("a" => 1, "b" => 2, "c" => 3);

// 5.4 及之后
$array = [1, 2, 3];
$array = ["a" => 1, "b" => 2, "c" => 3];

引申到另外一个问题上,如果我们要把数组的值赋值给不同的变量,可以通过 list 来实现:

<?php
list($a, $b, $c) = $array;

是否也可以通过 [] 的简写来实现呢?

<?php
[$a, $b, $c] = $array;

以及下一个特性中会提到的 list 指定 key

<?php
["a" => $a, "b" => $b, "c" => $c] = $array;

PHP7.1 实现了这个特性。但是要注意的是:出现在左值中的 [] 并不是数组的简写,是 list() 的简写。

但是并不仅仅如此,新的 list() 的实现并不仅仅可以出现在左值中,也能在 foreach 循环中使用:

<?php
foreach ($points as ["x" => $x, "y" => $y]) {
 var_dump($x, $y);
}

不过因为实现的问题,list() 和 [] 不能相互嵌套使用:

<?php
// 不合法
list([$a, $b], [$c, $d]) = [[1, 2], [3, 4]];

// 不合法
[list($a, $b), list($c, $d)] = [[1, 2], [3, 4]];

// 合法
[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];

三、允许在 list 中指定 key

上文提到过,新的 list() 的实现中可以指定key:

<?php
$array = ["a" => 1, "b" => 2, "c" => 3];
["a" => $a, "b" => $b, "c" => $c] = $array;

这也就相当于:

<?php
$a = $array['a'];
$b = $array['b'];
$c = $array['c'];

和以往的区别在于以往的 list() 的实现相当于 key 只能是 0, 1, 2, 3 的数字形式并且不能调整顺序。执行以下语句:

<?php
list($a, $b) = [1 => '1', 2 => '2'];

会得到 PHP error: Undefined offset: 0... 的错误。

而新的实现则可以通过以下方式来调整赋值:

<?php
list(1 => $a, 2 => $b) = [1 => '1', 2 => '2'];

不同于数组的是,list 并不支持混合形式的 key,以下写法会触发解析错误:

<?php
// Parse error: syntax error, ...
list($unkeyed, "key" => $keyed) = $array;

更复杂的情况,list 也支持复合形式的解析:

<?php
$points = [
 ["x" => 1, "y" => 2],
 ["x" => 2, "y" => 1]
];

list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points;

$points = [
 "first" => [1, 2],
 "second" => [2, 1]
];

list("first" => list($x1, $y1), "second" => list($x2, $y2)) = $points;

以及循环中使用:

<?php
$points = [
 ["x" => 1, "y" => 2],
 ["x" => 2, "y" => 1]
];

foreach ($points as list("x" => $x, "y" => $y)) {
 echo "Point at ($x, $y)", PHP_EOL;
}

四、void 返回类型

PHP7.0 添加了指定函数返回类型的特性,但是返回类型却不能指定为 void,7.1 的这个特性算是一个补充:

<?php
function should_return_nothing(): void {
 return 1; // Fatal error: A void function must not return a value
}

以下两种情况都可以通过验证:

<?php
function lacks_return(): void {
 // valid
}

function returns_nothing(): void {
 return; // valid
}

定义返回类型为 void 的函数不能有返回值,即使返回 null 也不行:

<?php
function returns_one(): void {
 return 1; // Fatal error: A void function must not return a value
}

function returns_null(): void {
 return null; // Fatal error: A void function must not return a value
}

此外 void 也只适用于返回类型,并不能用于参数类型声明,或者会触发错误:

<?php
function foobar(void $foo) { // Fatal error: void cannot be used as a parameter type
}

类函数中对于返回类型的声明也不能被子类覆盖,否则会触发错误:

<?php
class Foo
{
 public function bar(): void {
 }
}

class Foobar extends Foo
{
 public function bar(): array { // Fatal error: Declaration of Foobar::bar() must be compatible with Foo::bar(): void
 }
}

五、类常量属性设定

这个特性说起来比较简单,就是现在类中的常量支持使用 publicprivate protected 修饰了:

<?php
class Token {
 // 常量默认为 public
 const PUBLIC_CONST = 0;

 // 可以自定义常量的可见范围
 private const PRIVATE_CONST = 0;
 protected const PROTECTED_CONST = 0;
 public const PUBLIC_CONST_TWO = 0;

 // 多个常量同时声明只能有一个属性
 private const FOO = 1, BAR = 2;
}

此外,接口(interface)中的常量只能是 public 属性:

<?php
interface ICache {
 public const PUBLIC = 0;
 const IMPLICIT_PUBLIC = 1;
}

为了应对变化,反射类的实现也相应的丰富了一下,增加了 getReflectionConstant getReflectionConstants 两个方法用于获取常量的额外属性:

<?php
class testClass {
 const TEST_CONST = 'test';
}

$obj = new ReflectionClass( "testClass" );
$const = $obj->getReflectionConstant( "TEST_CONST" );
$consts = $obj->getReflectionConstants();

六、多条件 catch

在以往的 try ... catch 语句中,每个 catch 只能设定一个条件判断:

<?php
try {
 // Some code...
} catch (ExceptionType1 $e) {
 // 处理 ExceptionType1
} catch (ExceptionType2 $e) {
 // 处理 ExceptionType2
} catch (\Exception $e) {
 // ...
}

新的实现中可以在一个 catch 中设置多个条件,相当于或的形式判断:

<?php
try {
 // Some code...
} catch (ExceptionType1 | ExceptionType2 $e) {
 // 对于 ExceptionType1 和 ExceptionType2 的处理
} catch (\Exception $e) {
 // ...
}

对于异常的处理简化了一些。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用PHP7.1能有一定的帮助,如果有疑问大家可以留言交流。

附:源 RFC 地址

Nullable Types
Square bracket syntax for array destructuring assignment
Allow specifying keys in list()
Generalize support of negative string offsets
Void Return Type
Class constant visibility modifiers
Multi catch

PHP 相关文章推荐
对Session和Cookie的区分与解释
Mar 16 PHP
php的urlencode()URL编码函数浅析
Aug 09 PHP
PHP中通过语义URL防止网站被攻击的方法分享
Sep 08 PHP
递归删除一个节点以及该节点下的所有节点示例
Mar 19 PHP
PHP中strtr字符串替换用法详解
Nov 26 PHP
PHP中使用file_get_contents抓取网页中文乱码问题解决方法
Dec 17 PHP
PHP对文件夹递归执行chmod命令的方法
Jun 19 PHP
详解WordPress中的头像缓存和代理中的缓存更新方法
Mar 01 PHP
分享php多功能图片处理类
May 15 PHP
PHP插件PHPMailer发送邮件功能
Feb 28 PHP
php 将json格式数据转换成数组的方法
Aug 21 PHP
实例分析PHP将字符串转换成数字的方法
Jan 27 PHP
浅谈PHP命令执行php文件需要注意的问题
Dec 16 #PHP
PHP+Ajax 检测网络是否正常实例详解
Dec 16 #PHP
php微信公众号开发(4)php实现自定义关键字回复
Dec 15 #PHP
php微信公众号开发(3)php实现简单微信文本通讯
Dec 15 #PHP
php微信公众号开发(2)百度BAE搭建和数据库使用
Dec 15 #PHP
redis查看连接数及php模拟并发创建redis连接的方法
Dec 15 #PHP
php结合redis高并发下发帖、发微博的实现方法
Dec 15 #PHP
You might like
使用 php4 加速 web 传输
2006/10/09 PHP
使ecshop模板中可引用常量的实现方法
2011/06/02 PHP
PHP与Java进行通信的实现方法
2013/10/21 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
原来Jquery.load的方法可以一直load下去
2011/03/28 Javascript
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
侧栏跟随滚动的简单实现代码
2013/03/18 Javascript
JQuery中操作Css样式的方法
2014/02/12 Javascript
提高NodeJS中SSL服务的性能
2014/07/15 NodeJs
js表格排序实例分析(支持int,float,date,string四种数据类型)
2015/05/06 Javascript
jquery实现点击其他区域时隐藏下拉div和遮罩层的方法
2015/12/23 Javascript
老生常谈JavaScript 正则表达式语法
2016/08/20 Javascript
jQueryUI Datepicker组件设置日期高亮
2016/10/13 Javascript
微信小程序 绘图之饼图实现
2016/10/24 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
微信小程序tabBar 返回tabBar不刷新页面
2019/07/25 Javascript
浅谈Vue 函数式组件的使用技巧
2020/06/16 Javascript
解决Vue 给mapState中定义的属性赋值报错的问题
2020/06/22 Javascript
jQuery实现计算器功能
2020/10/19 jQuery
Python基础之循环语句用法示例【for、while循环】
2019/03/23 Python
对python 调用类属性的方法详解
2019/07/02 Python
python3应用windows api对后台程序窗口及桌面截图并保存的方法
2019/08/27 Python
基于python3监控服务器状态进行邮件报警
2019/10/19 Python
浅谈多卡服务器下隐藏部分 GPU 和 TensorFlow 的显存使用设置
2020/06/30 Python
python实现AHP算法的方法实例(层次分析法)
2020/09/09 Python
使用Html5多媒体实现微信语音功能
2019/07/26 HTML / CSS
ProBikeKit美国官网:自行车套件,跑步和铁人三项套件
2016/10/13 全球购物
德国古洛迷亚百货官网:GALERIA Kaufhof
2017/06/20 全球购物
澳大利亚第一的设计师礼服租赁网站:GlamCorner
2017/08/13 全球购物
捷克时尚网上商店:OTTO
2018/03/15 全球购物
华为智利官方商店:Huawei Chile
2020/05/09 全球购物
大唐电信科技股份有限公司java工程师面试经历
2016/12/09 面试题
5个HTML5的常用本地存储方式详解与介绍
2021/03/27 HTML / CSS
经济系大学生求职信
2013/10/01 职场文书
邻里守望志愿服务活动方案
2014/08/15 职场文书
七年级数学教学反思
2016/02/17 职场文书