PHP7带来的新特性
本文大部分内容参照“Backward incompatible changes - New features”编写,主要介绍PHP7相较PHP5带来的一些新特性。
##1. 参数、返回值类型声明
类型参数扩充了以下类型:string, int, float, bool。
支持返回值的类型声明,类型与参数类型一致。
若要对严格类型进行强制限制,则需要声明declare(strict_types=1)
<?php declare(strict_types=1);
/**
* [test description]
* @param int $a
* @param int $b
* @return int
*/
function test(int $a, int $b): int
{
return $a + $b;
}
//echo 3
echo test(1, '2'), PHP_EOL;##2. null合并运算符
经常会有使用三元运算符判断一个值如果存在即返回这个值,否则返回另一个值的情况,PHP7专门提供了这样一个运算符??来解决这个问题,当前一个值存在并且不为空,则返回,否则返回后一个值,请看下面的🌰,注意??和?:的区别。
<?php
$arr = array();
//PHP5&PHP7 : Notice: Undefined index: a in ..., 同时echo 10
echo ($arr['a'] ?: 10), PHP_EOL;
//PHP7 : echo 10
echo ($arr['a'] ?: 10), PHP_EOL;##3. 宇宙飞船运算符
这个符号<=>是不是很像宇宙飞船,实现的功能是比较两个值,大于: 1, 小于: -1, 等于: 0,看个🌰:
<?php
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1##4. define()可以支持数组
下面是官网的一个🌰:
<?php
define('ANIMALS', [
'dog',
'cat',
'bird'
]);##4. 匿名类
可以通过new来实例化一个匿名类,看官网的🌰:
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
//此处注意匿名类
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());##5. Unicode码转译
使用双引号包裹的以\u{开始的字符串将会进行“Unicode码转译”,\u{可以跟着0,在转译时前面的0将会被忽略。注意如果是从PHP5升级到PHP7的并且有使用过\u{字符的要将反斜杠转义,否则会异常,具体的可以看从PHP5到PHP7,下面是官网提供的🌰:
<?php
echo "\u{aa}"; //ª
echo "\u{0000aa}"; //ª
echo "\u{9999}"; //香##6. 新增Closure::call()方法
闭包与对象临时绑定并调用,变得更加简单,看下官网提供的🌰:
<?php
class A {private $x = 1;}
// Pre PHP 7 code
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
echo $getX();
// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);更多细节查看Closure::call
##7. unserialize() 过滤功能
unserialize()支持设置白名单功能,使得当反序列化不可靠的数据时更加安全,看🌰:
<?php
// converts all objects into __PHP_Incomplete_Class object
$data = unserialize($foo, ["allowed_classes" => false]);
// converts all objects into __PHP_Incomplete_Class object except those of MyClass and MyClass2
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
// default behaviour (same as omitting the second argument) that accepts all classes
$data = unserialize($foo, ["allowed_classes" => true]);更多细节请查看unserialize()。
##8. 新增IntlChar
暴露了很多ICU库的方法,以获取Unicode字符的相关信息,更多信息请查看IntlChar。
##9. 预期(assert的增强)
预期是对assert()功能的一个增强,它降低了assert()的使用成本,并且能够支持断言失败是抛出异常。
出于兼容之前assert()的目的,将assert.exception设置为disable时,assert将按照前的方式执行。
<?php
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
//echo Fatal error: Uncaught CustomError: Some error message...
assert(false, new CustomError('Some error message'));更多内容,请查看:expectations section
##10. use 组声明
可以通过一个use导入多个 类、方法和常量,看下官网给出的🌰:
<?php
// Pre PHP 7 code
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// PHP 7+ code
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};##11. Generator 支持 return 表达式
Generator中支持return,return值可以通过getReturn()方法获得,但是必须要在Generator迭代结束以后,否则会抛出Fatal error,看下下面使用的🌰:
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;##12. Generator 代理
Generator可以代理到其他的Generator 和 一切实现了Traversable的对象 或 数组,使用yield from实现Generator代理功能,看下面的🌰:
<?php
function generator()
{
yield 1;
yield 2;
yield from generator_delegate_test(); //代理 Generator
yield from array('a', 'b', 'c'); //代理 array
}
function generator_delegate_test()
{
yield 3;
yield 4;
}
foreach (generator() as $val)
{
echo $val, PHP_EOL;
}##12. intdiv() 整数除法
个人理解,intdiv($a, $b) ≈ intval($a / $b) ≈ $a / $b >> 0。
注意,当0作为被除数时,会抛出DivisionByZeroError;如果被除数为PHP_INT_MIN并且除数为-1时,会抛出ArithmeticError,原因是正常计算的情况下PHP_INT_MIN除以-1得到的数字超出了PHP整数的最大范围,看下🌰:
<?php
//echo 3
echo intdiv(10, 3). PHP_EOL;
//Fatal error: Uncaught DivisionByZeroError: Division by zero in ...
echo intdiv(1, 0). PHP_EOL;
//Fatal error: Uncaught ArithmeticError: Division of PHP_INT_MIN by -1 is not an integer in ...
echo intdiv(PHP_INT_MIN, -1). PHP_EOL;
//echo PHP_INI_MAX
echo intdiv(PHP_INT_MIN + 1, -1). PHP_EOL;##Session 选项
session_start()方法,现在支持一个array()参数,数组内容会覆盖掉php.ini中的配置,看🌰:
<?php
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);##preg_replace_callback_array()
preg_replace_callback可支持function数组,看下面的🌰:
<?php
$str = 'Aaaaa bbbb cccc';
$result = preg_replace_callback_array(
[
'/a/i' => function ($match) {
return 1;
},
'/b/i' => function ($match) {
return 2;
}
],
$str
);
//echo 11111 2222 cccc
echo $result, PHP_EOL;更多细节,请看:preg_replace_callback_array
##CSPRNG 方法
加入了两个新方法random_bytes() 和 random_int(),🌰:
<?php
//生成一个50个字符长度的随机串
echo random_bytes(50), PHP_EOL;
//生成一个1 ~ 50之间的字符串
echo random_int(1, 50), PHP_EOL;list() 能够正确处理ArrayAccess
之前版本list()不能保证正确处理所有ArrayAccess,在PHP7中解决了这个问题。