php 7+新特性
本文摘自php中文网
PHP5.2至5.6的新增功能详解
php7新增功能
1、在use语句增加了group支持
use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo };
2、增加??操作符
isset($_GET['mykey']) ? $_GET['mykey'] : "笨重"; $_GET['mykey'] ?: "" ;//当mykey不存在时会报一个E_NOTICE $_GET['mykey'] ?? 'defaultvalue' ;//安全不会报E_NOTICE $username = $_GET['user'] ?? 'nobody';//相当于$username=$_GET['user']?$_GET['user']:'nobody';
3、64位PHP7字符串长度可以超过2^31次方字节。
4、增加Closure::call支持 Closure::call将一个闭包函数动态绑定到一个新的对象实例并调用执行该函数,
class Value { protected $value; public function __construct($value) { $this->value = $value; } public function getValue() { return $this->value; } } $three = new Value(3); $four = new Value(4); $closure = function ($delta) { var_dump($this->getValue() + $delta); }; $closure->call($three, 4); $closure->call($four, 4); // outputs int(7),int(8)
class Test { public $name = "lixuan"; } //PHP7和PHP5.6都可以 $getNameFunc = function () { return $this->name; }; $name = $getNameFunc->bindTo(new Test, 'Test'); echo $name(); //PHP7可以,PHP5.6报错 $getX = function () { return $this->name; }; echo $getX->call(new Test);
5、Unicode codepoint 转译语法
双引号字符串和heredocs里面支持使用\u{xxxxx}来声明unicode字符。
这接受一个以16进制形式的 Unicode codepoint,并打印出一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的
//\u9876 echo "\u{9876}"; //旧版输出:\u{9876} //新版输入:顶
6、define对数组的支持
define('ANIMALS', array('dog','cat','bird')); echo ANIMALS[1]; // outputs "cat"
7、增加比较运算符<=>(太空船操作符)
$a <=> $b //如果a等于b则为0 //如果a大于b则为1 //如果a小于b则为-1
8、php全局保留字可以声明使用
class View { public function include(View $view) { //... //include关键字可以当普通字符串关键字一样被使用 } }
9、标量类型(int,float,string,bool)支持
增加declare(strict_types=1)指令声明是否严格类型校验,
当在文件头声明declare(strict_types=1)
declare(strict_types=1); function add(float $a, float $b): float { return $a + $b; } add(1, 2); // float(3) 参数必须为浮点数了
以上代码如果不开启declare(strict_types=1)或许declare(strict_types=0),php将自动转换参数和返回值到指定类型,
开启declare(strict_types=1),如果参数类型不是flaot或许返回类型不是float则抛出错误
10、增加接口为用户层提供安全方便的随机数生成器。RFC: https://wiki.php.net/rfc/easy_userland_csprng (后续再议)
11、增加了yield from 操作符。https://wiki.php.net/rfc/generator-delegation (后续再议)
12、返回值类型的声明,有以下申明的类型:
- int
- float
- bool
- string
- interfaces
- array
- callable
function show(): array { return [1,2,3,4]; } function arraysSum(array ...$arrays): array { //array_map('自定义函数',arr_1,...arr_n);将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。 //回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致 return array_map( function(array $array): int { return array_sum($array); }, $arrays ); }
返回类型声明 如果不做类型强制约束,那么PHP会将返回的数据转化为指定类型的数据再返回,目前差不多只有string无法强转为int才会报错。
如果指定了强制约束,那么PHP将不会进行类型转换,而是进行对比,如类型不同,则报错。
还有,返回值类型,也可指定对象名,则必须返回指定对象的实例,如:
class person { private function __construct($name) { $this->name = $name; } static function instance(string $name) : person { return new self($name); } } person::instance('zhangsan');
13、函数形参类型申明 PHP 7 支持的形参类型申明的类型有以下几种:
- 整型
- 浮点型
- 字符串型
- 布尔类型
class Demo{ /** * int $age 则是形参类型声明 * : int 是返回类型声明 */ public function age(int $age) : int { return $age; } } $demo = new Demo(); $demo->age(23);//通过 $demo->age(10.23); // 我们传递的是 float 型参数,也能通过检查 //上面传入float能通过检查是因为在 php7 中,默认情况下形参类型说明不是完全被限制的,这就意味着我们定义的东西只是一个建议,而不是完全约束 //我们要完全限制则需要通过上面第九的declare(strict_type=1);来申明完全限制,这时候就会报Uncaught Type Error的错
14、为unserialize()提供过滤
//将所有对象分为__PHP_Incomplete_Class对象 $data = unserialize($foo, ["allowed_classes" => false]); //将所有对象分为__PHP_Incomplete_Class 对象 除了ClassName1和ClassName2 $data = unserialize($foo, ["allowed_classes" => ["ClassName1", "ClassName2"]); //默认行为,和 unserialize($foo)相同 $data = unserialize($foo, ["allowed_classes" => true]);
15、新增加的 IntlChar 类旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。Intl是Pecl扩展,使用前需要编译进PHP中,也可apt-get/yum/port install php5-intl
printf('%x', IntlChar::CODEPOINT_MAX); echo IntlChar::charName('@'); var_dump(IntlChar::ispunct('!'));
以上例程会输出:
10ffff
COMMERCIAL AT
bool(true)
16、intdiv 接收两个参数作为被除数和除数,返回他们相除结果的整数部分。
var_dump(intdiv(7, 2));//int(3)
17、CSPRNG
新增两个函数:
random_bytes — 加密生存被保护的伪随机字符串
random_int —加密生存被保护的伪随机整数
18、新增了一个函数preg_replace_callback_array(),使用该函数可以使得在使用preg_replace_callback()函数时代码变得更加优雅。在PHP7之前,回调函数会调用每一个正则表达式,回调函数在部分分支上是被污染了
19、现在,session_start()函数可以接收一个数组作为参数,可以覆盖php.ini中session的配置项。
比如,把cache_limiter设置为私有的,同时在阅读完session后立即关闭
session_start(['cache_limiter' => 'private', 'read_and_close' => true, ]);
19、生成器的返回值(读取超大文件)
在PHP5.5引入生成器的概念。生成器函数每执行一次就得到一个yield标识的值。在PHP7中,当生成器迭代完成后,可以获取该生成器函数的返回值。通过Generator::getReturn()得到
function generator() { yield 1; yield 2; yield 3; return "a"; } $generatorClass =generator(); foreach ($generatorClass as $val) { echo $val ." "; } echo $generatorClass->getReturn();
首先执行函数 该函数遇到yield停止并将该yied的值发送给foreach
20、生成器中引入其他生成器 在生成器中可以引入另一个或几个生成器,只需要写yield from functionName1
function generator1() { yield 1; yield 2; yield from generator2(); yield from generator3(); } function generator2() { yield 3; yield 4; } function generator3() { yield 5; yield 6; } foreach (generator1() as $val) { echo $val, " "; }
php7不兼容:
foreach不再改变内部数组指针
$array = [0, 1, 2]; foreach ($array as &$val) { var_dump(current($array)); } PHP5输出: int(1) int(2) bool(false) PHP7输出: int(0) int(0) int(0)
foreach通过引用遍历时,有更好的迭代特性
$array = [0]; foreach ($array as &$val) { var_dump($val); $array[1] = 1; } PHP5输出: int(0) PHP7输出: int(0) int(1)
十六进制字符串不再被认为是数字
var_dump("0x123" == "291"); var_dump(is_numeric("0x123")); var_dump("0xe" + "0x1"); var_dump(substr("foo", "0x1")); PHP5输出: bool(true) bool(true) int(15) string(2) “oo” PHP7输出: bool(false) bool(false) int(0) Notice: A non well formed numeric value encountered in /tmp/test.php on line 5 string(3) “foo”
PHP7中被移除的函数
被移除的函数列表如下:
call_user_func() 和 call_user_func_array()从PHP 4.1.0开始被废弃。
已废弃的 mcrypt_generic_end() 函数已被移除,请使用mcrypt_generic_deinit()代替。
已废弃的 mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() 和 mcrypt_ofb() 函数已被移除。
set_magic_quotes_runtime(), 和它的别名 magic_quotes_runtime()已被移除. 它们在PHP 5.3.0中已经被废弃,并且 在in PHP 5.4.0也由于魔术引号的废弃而失去功能。
已废弃的 set_socket_blocking() 函数已被移除,请使用stream_set_blocking()代替。
dl()在 PHP-FPM 不再可用,在 CLI 和 embed SAPIs 中仍可用。
GD库中下列函数被移除:imagepsbbox()、imagepsencodefont()、imagepsextendfont()、imagepsfreefont()、imagepsloadfont()、imagepsslantfont()、imagepstext()
在配置文件php.ini中,always_populate_raw_post_data、asp_tags、xsl.security_prefs被移除了。
new 操作符创建的对象不能以引用方式赋值给变量
new 操作符创建的对象不能以引用方式赋值给变量
class C {}
$c =& new C;
PHP5输出:
Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3
PHP7输出:
Parse error: syntax error, unexpected ‘new’ (T_NEW) in /tmp/test.php on line 3
移除了 ASP 和 script PHP 标签
使用类似 ASP 的标签,以及 script 标签来区分 PHP 代码的方式被移除。 受到影响的标签有:<% %>、<%= %>、
从不匹配的上下文发起调用
在不匹配的上下文中以静态方式调用非静态方法, 在 PHP 5.6 中已经废弃, 但是在 PHP 7.0 中, 会导致被调用方法中未定义 $this 变量,以及此行为已经废弃的警告。
class A { public function test() { var_dump($this); } } // 注意:并没有从类 A 继承 class B { public function callNonStaticMethodOfA() { A::test(); } } (new B)->callNonStaticMethodOfA();
PHP5输出:
Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8
object(B)#1 (0) {
}
PHP7输出:
Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8
Notice: Undefined variable: this in /tmp/test.php on line 3
NULL
在数值溢出的时候,内部函数将会失败
将浮点数转换为整数的时候,如果浮点数值太大,导致无法以整数表达的情况下, 在之前的版本中,内部函数会直接将整数截断,并不会引发错误。 在 PHP 7.0 中,如果发生这种情况,会引发 E_WARNING 错误,并且返回 NULL。
JSON 扩展已经被 JSOND 取代
JSON 扩展已经被 JSOND 扩展取代。
对于数值的处理,有以下两点需要注意的:
第一,数值不能以点号(.)结束 (例如,数值 34. 必须写作 34.0 或 34)。
第二,如果使用科学计数法表示数值,e 前面必须不是点号(.) (例如,3.e3 必须写作 3.0e3 或 3e3)。
INI 文件中 # 注释格式被移除
在配置文件INI文件中,不再支持以 # 开始的注释行, 请使用 ;(分号)来表示注释。 此变更适用于 php.ini 以及用 parse_ini_file() 和 parse_ini_string() 函数来处理的文件。
$HTTP_RAW_POST_DATA 被移除
不再提供 $HTTP_RAW_POST_DATA 变量。 请使用 php://input 作为替代。
yield 变更为右联接运算符
在使用 yield 关键字的时候,不再需要括号, 并且它变更为右联接操作符,其运算符优先级介于 print 和 => 之间。 这可能导致现有代码的行为发生改变。可以通过使用括号来消除歧义。
echo yield -1; // 在之前版本中会被解释为: echo (yield) - 1; // 现在,它将被解释为: echo yield (-1);
yield $foo or die; // 在之前版本中会被解释为: yield ($foo or die); // 现在,它将被解释为: (yield $foo) or die;
php7.1 新增功能
1.可为空(Nullable)类型
参数和返回值的类型声明可以通过在类型名称前添加一个问号(?
)来标记为空(null)。表明函数参数或者返回值的类型要么为指定类型,要么为 null。
看下例子:
function testReturn(?string $name){ return $name; } var_dump(testReturn('yangyi'));//yangyi var_dump(testReturn(null));//null 7.1新特性 var_dump(testReturn2());//致命错误
打印输出:
如上如:第三个报了一个致命的错误。
再来看下,函数返回值是Nullable
的情况:
function testReturn3() : ?string{ //return "abc"; //return null; } var_dump(testReturn3());
如果加了?
要么返回 string ,要么返回null。不能啥也不返还。会报错。
2.void返回类型
PHP7.0 添加了指定函数返回类型的特性,但是返回类型却不能指定为 void,7.1 的这个特性算是一个补充。定义返回类型为 void
的函数不能有返回值,即使返回 null 也不行:
function testReturn4() : void{ //1. 要么啥都不返还 ok //2. 要么只return; ok //return; //3. return null 也会报错 //return null; //4. return 4 会报错 //return 4;
}
Fatal error: A void function must not return a value in /php71.php on line 70
还有就是,void 只能用于返回值,不能用于参数中。比如下面的会报错:
function testReturn6(void $a) : void{} var_dump(testReturn6());
PHP Fatal error: void cannot be used
as
a parameter type in php71.php on line 73
如果在类的继承中,申明为void返回类型的方法,子类要是继承重写,也只能返回void, 否则会触发错误:
<?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 } }
所以,你必须这样,就不会报错:
class Foo{ public $a; public function bar(): void { $this->a = 2; } }
class Foobar extends Foo{ // 覆盖成功 public function bar(): void { $this->a = 3; } }
3.list 的方括号([]
)简写以及增加指定key
可以用list 来快速遍历得到数组里面的值。现在可以用[]
简写了。
$data = [ [1, 'Tom'], [2, 'Fred'], ]; // list() stylelist($id1, $name1) = $data[0]; // [] style[$id1, $name1] = $data[0]; // list() styleforeach ($data as list($id, $name)) { // logic here with $id and $name}
// [] styleforeach ($data as [$id, $name]) { // logic here with $id and $name //}
此外,此次更新的list,针对索引数组,还可以指定 key,这个升级非常棒,非常方便。 list()现在支持键名
$data = [ ["id" => 1, "name" => 'Tom'], ["id" => 2, "name" => 'Fred'], ];// list() stylelist("id" => $id1, "name" => $name1) = $data[0]; // [] style["id" => $id1, "name" => $name1] = $data[0]; // list() styleforeach ($data as list("id" => $id, "name" => $name)) { // logic here with $id and $name } // [] styleforeach ($data as ["id" => $id, "name" => $name]) { // logic here with $id and $name}
在这个功能没有之前,我们一般会用while
+ each
的方式来用list
遍历索引数组:
$data = [ ["id" => 1, "name" => 'Tom'], ["id" => 2, "name" => 'Fred'], ];while (list($id, name) = each($data)) { echo "$key => $val\n"; }
注意:PHP 7.2 中已经将 each 函数移除了!所以,就不要用这种方式来遍历索引数组了
短数组语法([])现在可以用于将数组的值赋给一些变量(包括在foreach中)。 这种方式使从数组中提取值变得更为容易。
$data = [ ['id' => 1, 'name' => 'Tom'], ['id' => 2, 'name' => 'Fred'], ]; while (['id' => $id, 'name' => $name] = $data) { // logic here with $id and $name }
3.类常量可见范围设定
之前类里面额常量用const
申明,是没有可见属性的。现在把方法的可见属性移植了过来:
<?php class ConstDemo { // 常量默认为 public const PUBLIC_CONST = 0; // 可以自定义常量的可见范围 public const PUBLIC_CONST_B = 2; protected const PROTECTED_CONST = 3; private const PRIVATE_CONST = 4; // 多个常量同时声明只能有一个属性 private const FOO = 1, BAR = 2; }
4.支持负的字符串偏移使用方法和类的方法一样。就不多详述了。
有2个更新,1是字符串直接取,2是strpos函数第三个参数支持负数。表示从尾部取。
var_dump("abcdef"[-2]); // evar_dump(strpos("aabbcc", "b", -3)); //3
string变量可以直接取值,不用通过变量名,是在php5.5加入的。现在可以从尾部取:
var_dump("abcdef"[-2]); // 从末尾取倒数第2个字符:evar_dump("abcdef"[2]); // 从前面取第2个,从0开始:c$string = 'bar';echo $string[1], $string[-1]; // a r
5.多条件 catch
在以往的 try … catch 语句中,每个 catch 只能设定一个条件判断:
try { // Some code...} catch (ExceptionType1 $e) { // 处理 ExceptionType1} catch (ExceptionType2 $e) { // 处理 ExceptionType2} catch (Exception $e) { // ...}
现在可以多个一起处理。用”|
” 分割。
try { // Some code... } catch (ExceptionType1 | ExceptionType2 $e) { // 对于 ExceptionType1 和 ExceptionType2 的处理 } catch (Exception $e) { // ...}
6.iterable 伪类
现在引入了一个新的被称为iterable的伪类 (与callable类似)。 这可以被用在参数或者返回值类型中,它代表接受数组或者实现了Traversable接口的对象。 至于子类,当用作参数时,子类可以收紧父类的iterable类型到array 或一个实现了Traversable的对象。对于返回值,子类可以拓宽父类的 array或对象返回值类型到iterable。
function iterator(iterable $iter) { foreach ($iter as $val) { // } }
7.ext/openssl 支持 AEAD
通过给openssl_encrypt()和openssl_decrypt() 添加额外参数,现在支持了AEAD (模式 GCM and CCM)。
通过 Closure::fromCallable() 将callables转为闭包
Closure新增了一个静态方法,用于将callable快速地 转为一个Closure 对象。
class Test { public function exposeFunction() { return Closure::fromCallable([$this, 'privateFunction']); } private function privateFunction($param) { var_dump($param); } } $privFunc = (new Test)->exposeFunction(); $privFunc('some value'); //string(10) "some value"
8.异步信号处理 Asynchronous signal handling
A new function called pcntl_async_signals() has been introduced to enable asynchronous signal handling without using ticks (which introduce a lot of overhead).
增加了一个新函数 pcntl_async_signals()来处理异步信号,不需要再使用ticks(它会增加占用资源)
pcntl_async_signals(true); // turn on async signals pcntl_signal(SIGHUP, function($sig) { echo "SIGHUP\n"; }); posix_kill(posix_getpid(), SIGHUP);
以上例程会输出:SIGHUP
9.HTTP/2 服务器推送支持 ext/curl
Support for server push has been added to the CURL extension (requires version 7.46 and above). This can be leveraged through the curl_multi_setopt() function with the new CURLMOPT_PUSHFUNCTION constant. The constants CURL_PUST_OK and CURL_PUSH_DENY have also been added so that the execution of the server push callback can either be approved or denied.
蹩脚英语:
对于服务器推送支持添加到curl扩展(需要7.46及以上版本)。
可以通过用新的CURLMOPT_PUSHFUNCTION常量 让curl_multi_setopt()函数使用。
也增加了常量CURL_PUST_OK和CURL_PUSH_DENY,可以批准或拒绝 服务器推送回调的执行
php7.1不兼容性
1.当传递参数过少时将抛出错误
在过去如果我们调用一个用户定义的函数时,提供的参数不足,那么将会产生一个警告(warning)。 现在,这个警告被提升为一个错误异常(Error exception)。这个变更仅对用户定义的函数生效, 并不包含内置函数。例如:
function test($param){} test(); 输出: Uncaught Error:Too few arguments to function test(), 0 passed in %s on line %d and exactly 1 expected in %s:%d
2.禁止动态调用函数
禁止动态调用函数如下
assert() - with a string as the first argument
compact()
extract()
func_get_args()
func_get_arg()
func_num_args()
get_defined_vars()
mb_parse_str() - with one arg
parse_str() - with one arg
(function () { 'func_num_args'(); })(); 输出 Warning: Cannot call func_num_args() dynamically in %s on line %d
3.无效的类,接口,trait名称命名
以下名称不能用于 类,接口或trait 名称命名:
void
iterable
4.Numerical string conversions now respect scientific notation
Integer operations and conversions on numerical strings now respect scientific notation. This also includes the (int) cast operation, and the following functions: intval() (where the base is 10), settype(), decbin(), decoct(), and dechex().
5.mt_rand 算法修复
mt_rand() will now default to using the fixed version of the Mersenne Twister algorithm. If deterministic output from mt_srand() was relied upon, then the MT_RAND_PHP with the ability to preserve the old (incorrect) implementation via an additional optional second parameter to mt_srand().
6.rand() 别名 mt_rand() 和 srand() 别名 mt_srand()
rand() and srand() have now been made aliases to mt_rand() and mt_srand(), respectively. This means that the output for the following functions have changes: rand(), shuffle(), str_shuffle(), and array_rand().
7.Disallow the ASCII delete control character in identifiers
The ASCII delete control character (0x7F) can no longer be used in identifiers that are not quoted.
8.error_log changes with syslog value
If the error_log ini setting is set to syslog, the PHP error levels are mapped to the syslog error levels. This brings finer differentiation in the error logs in contrary to the previous approach where all the errors are logged with the notice level only.
9.在不完整的对象上不再调用析构方法
析构方法在一个不完整的对象(例如在构造方法中抛出一个异常)上将不再会被调用
10.call_user_func()不再支持对传址的函数的调用
call_user_func() 现在在调用一个以引用作为参数的函数时将始终失败。
11.字符串不再支持空索引操作符 The empty index operator is not supported for strings anymore
对字符串使用一个空索引操作符(例如str[]=x)将会抛出一个致命错误, 而不是静默地将其转为一个数组
12.ini配置项移除
下列ini配置项已经被移除:
session.entropy_file
session.entropy_length
session.hash_function
session.hash_bits_per_character
PHP 7.1.x 中废弃的特性
1.ext/mcrypt
mcrypt 扩展已经过时了大约10年,并且用起来很复杂。因此它被废弃并且被 OpenSSL 所取代。 从PHP 7.2起它将被从核心代码中移除并且移到PECL中。
2.mb_ereg_replace()和mb_eregi_replace()的Eval选项
对于mb_ereg_replace()和mb_eregi_replace()的 e模式修饰符现在已被废弃
php7.2
php 7.2大都是底层的更新,提高性能。没有太大常用语法层面的更新,这里就略过了。
之前写过php7.0以及老版本的php各大版本的跟新点以及新功能。今天看下php7.1和php7.2的新功能。
相关推荐: