一、[php7系列]--php7里的返回类型声明和标量类型声明
php7里增加了返回类型声明和标题类型声明,可以理解为对一个方法的输入输出进行了类型验证,在PHP7之前,方法里的数组、对象参数是有类型声明的,但其它的整数、字符串等类型声明没有。这次在PHP7里也加上了。返回类型声明,之前的版本里都没有,这次都全部加上。
返回类型声明的示例如下:
function getDoctor() : Doctor { return 'here:this is string,not a class!';
}
$doctor = getDoctor();
如果在PHP7下运行会报错:TypeException: Return value of getDoctor() must be an instance of Doctor, string returned,即上面的方法要求了返回类必须是Doctor的实例化的类,而当前方法返回的是字符串。所以报错。
参数类型声明(标量类型声明)也差不多,在原来的类、数组的基础上增加:int、float、string和bool四个类型,需要注意的是虽然PHP7使用了标题类型声明,但并非是强制使用,有一个strict_types/declare()指令,可以声明是采用弱类型校验模式(可当做不检验,和PHP7之前的版本一样)和严格类型校验模式(根据类型声明严格检验)。
默认情况下,所有的PHP文件都处于弱类型校验模式。新的declare指令,通过指定strict_types的值(1或者0),1表示严格类型校验模式,作用于函数调用和返回语句;0表示弱类型校验模式。声明的语法:
declare(strict_types=1); #declare(strict_types=1)必须是文件的第一个语句,否则会产生一个编译错误。
strict_types指令只影响指定使用的文件,不会影响被它包含(通过include等方式)进来的其他文件。该指令在运行时编译,不能修改。它的运作方式,是在opcode中设置一个标志位,让函数调用和返回类型检查符合类型约束。
新增的这些类型声明定义对性能并没有提升, 相反引入了严格的类型检查, 在正常的情况下反而会加大runtime的开销,见鸟哥在知乎上的回复:这个特性的本意也不是为了性能考虑,当然, 类型提示会对类型推断起到帮助作用, PHP 7.1中已经加入了"类似"JIT的技术(type specifical opcode handler), 比如 如果类型推断出$a 是int , $b 是int, 那么 $a+$b 就可以使用ZEND_ADD_LONG handler, 从而间接的提高性能.但是, 总的来说, 这个特性的最初出发点, 并不是为了性能。
我觉得这是一个很好的改变,特别是返回类型的要求,因为在程序开发中,有时我们预期返回一个数组,但是写的时候可能不注意,在某些case的时候直接返回了false之类的,而在处理时又未加上数组判断,导致线上某些CASE下出现了问题。所以还是挺有作用。当然也不建议所有的地方都有必要这样使用。
二、不要用isset判断数组是否定义某个KEY-最好使用array_key_exists
(publish:June 16, 2017 -Friday) 之前没有碰到这个小问题,习惯了判断数组中有没有某个键值时,总是用isset($array[$key]).但今天在测试一个项目时发现这个判断离奇地不起作用了。影响代码:
if(isset($array[$key])) unset($array[$key]));
就是这么一句简单的代码,作用是避免将这个字段抛到接口层。后来发现这个数据从数据库里取出来,其值为null;其实我非常讨厌null这个东西,因为总会有奇怪的事情发生。但是后端内容控制后台是别的同事开发,我也提过null这个东西,但人家就那样。得了吧,我们就前端控制。很多地方对输出字段进行判断,如果值为空(包含null),我们就把值置成空字符串,否则接口里会直接显示null的。严重甚至导致APP端上崩溃。不过在处理了这么多地方后原来还有这么一个小坑。
问题找到了就没有啥了,原因就是isset判断数组是否有某个KEY时,如果值为NULL,是不会返回TRUE的。
#数据库表里的字段
$hello = null;
$arr = array('hellos' => null);#变量值为null或者数组某个KEY对应的值为NULL。isset返因的都是false;如下
if(isset($hello)) echo 'yes hello;<br>';
else echo 'no hello;<br>';
if(isset($arr['hellos'])) echo 'yes hellos;<br>';
else echo 'no hellos;<br>';
那怎么判断是否定义了某个变量呢(值为null)和某个数组的KEY呢(KEY对应的值为NULL)。数组的方法里实际有这么一个方法:array_key_exists,对于变量,可以去取全局已定义变量数组来判断,程序如下:
#判断数组有没有定义KEY:
if(array_key_exists('hellos', $arr)) echo 'yes hellos key;<br>';
else echo 'no hellos key;<br>';#is_null无论是没定义或者值为null都认为是null;有点像用isset判断是否定义数组的KEY一样
if(is_null ($hello)) echo '---yes $hello is null;<br>';
if(is_null ($hello22)) echo '---yes $hello22 is null;<br>';#判断定义了一个null变量
$vars = (array)get_defined_vars();
if(array_key_exists('hello', $vars) && !isset($hello) ) echo 'yes $hello is null;<br>';
输出结果:
no hello;
no hellos;
yes hellos key;
---yes $hello is null;
---yes $hello22 is null;
yes $hello is null;