一.PHP5.6.x 移植PHP7.0.x 1、PHP7.0.x 新特性
1.1 太空船操作符(组合比较符) (<=>) 太空船操作符用于比较两个表达式,当$a小于、等于或大于$b时它分别返回-1、0或1,比较规则延续常规比较规则。对象不能进行比较 。
<?php echo 1 <=> 1 ; echo 1 <=> 2 ; echo 2 <=> 1 ; echo 1.5 <=> 1.5 ; echo 1.5 <=> 2.5 ; echo 2.5 <=> 1.5 ; echo "a" <=> "a" ; echo "a" <=> "b" ; echo "b" <=> "a" ; ?>
1.2 null合并运算符 由于日常使用中存在大量同时使用三元表达式和 isset()的情况, 我们添加了null合并运算符 (??) 这个语法糖。如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。
<?php $a = isset ($_GET['a' ]) ? $_GET['a' ] : 'none' ; $a = isset ($_GET['a' ]) ?? 'none' ;
1.3 变量类型声明 变量类型声明有两种模式。一种是强制的,和严格的。允许使用下列类型参数int、string、float、bool
非严格模式
<?php function sumOfInts (int ...$ints ) { return array_sum($ints); } var_dump(sumOfInts(2 , '3' , 4.1 ));
严格模式
<?php declare (strict_types=1 );function add (int $x, int $y ) { return $x + $y; } var_dump(add('2' , 3 ));
要使用严格模式,一个declare声明指令必须放在文件的顶部。这意味着严格声明标量是基于文件可配的。 这个指令不仅影响参数的类型声明,也影响到函数的返回值声明
增加了返回类型声明,类似参数类型。这样更方便的控制函数的返回值.在函数定义的后面加上:类型名即可
<?php function fun (int $a ): array { return $a; } fun(3 );
1.5 匿名类 php7允许new class {} 创建一个匿名的对象。
<?php class Logger { public function log ($msg ) { echo $msg; } } $util->setLogger(new Logger()); $util->setLogger(new class { public function log ($msg ) { echo $msg; } });
1.6 Unicode codepoint 转译语法 这接受一个以16进制形式的 Unicode codepoint,并打印出一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的
<?php echo "\u{aa}" ;echo "\u{0000aa}" ;echo "\u{9999}" ;
1.7 Closure::call 闭包绑定 简短干练的暂时绑定一个方法到对象上闭包并调用它。
<?php class A {private $x = 1 ;} $getXCB = function ( ) {return $this ->x;}; $getX = $getXCB->bindTo(new A, 'A' ); echo $getX(); $getX = function ( ) {return $this ->x;};echo $getX->call(new A);
提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入
<?php $data = unserialize($foo, ["allowed_classes" => false ]); $data = unserialize($foo, ["allowed_classes" => ["MyClass" , "MyClass2" ]); $data = unserialize($foo, ["allowed_classes" => true ]);
1.9 IntlChar类 新增加的 IntlChar 类旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。
<?php printf('%x' , IntlChar::CODEPOINT_MAX);echo IntlChar::charName('@' ); var_dump(IntlChar::ispunct('!' ));
若要使用此类,请先安装Intl扩展
1.10 预期 预期是向后兼用并增强之前的 assert() 的方法。 它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。
<?php ini_set('assert.exception' , 1 );class CustomError extends AssertionError {} assert(false , new CustomError('Some error message' ));?>
1.11 命名空间按组导入 从同一个命名空间下导入的类、函数、常量支持按组一次导入
<?php use app \model \A ;use app \model \B ;use app \model {A ,B }
1.12 生成器支持返回表达式 此特性基于 PHP 5.5 版本中引入的生成器特性构建的。 它允许在生成器函数中通过使用 return 语法来返回一个表达式 (但是不允许返回引用值), 可以通过调用 Generator::getReturn() 方法来获取生成器的返回值, 但是这个方法只能在生成器完成产生工作以后调用一次。
<?php $gen = (function ( ) { yield 1 ; yield 2 ; return 3 ; })();foreach ($gen as $val) { echo $val, PHP_EOL; }echo $gen->getReturn(), PHP_EOL;
1.13 生成器委派 现在,只需在最外层生成其中使用 yield from, 就可以把一个生成器自动委派给其他的生成器, Traversable 对象或者 array。
<?php function gen ( ) { yield 1 ; yield 2 ; yield from gen2(); }function gen2 ( ) { yield 3 ; yield 4 ; }foreach (gen() as $val) { echo $val, PHP_EOL; }?>
<?php var_dump(intdiv(10 ,3 ));
1.15 会话选项设置 session_start() 可以加入一个数组覆盖php.ini的配置
<?php session_start([ 'cache_limiter' => 'private' , 'read_and_close' => true , ]);
<?php $tokenStream = []; $input = <<<'end' $a = 3; // variable initialisationend; preg_replace_callback( [ '~\$[a-z_][a-z\d_]*~i' , '~=~' , '~[\d]+~' , '~;~' , '~//.*~' ], function ($match ) use (&$tokenStream ) { if (strpos($match[0 ], '$' ) === 0 ) { $tokenStream[] = ['T_VARIABLE' , $match[0 ]]; } elseif (strpos($match[0 ], '=' ) === 0 ) { $tokenStream[] = ['T_ASSIGN' , $match[0 ]]; } elseif (ctype_digit($match[0 ])) { $tokenStream[] = ['T_NUM' , $match[0 ]]; } elseif (strpos($match[0 ], ';' ) === 0 ) { $tokenStream[] = ['T_TERMINATE_STMT' , $match[0 ]]; } elseif (strpos($match[0 ], '//' ) === 0 ) { $tokenStream[] = ['T_COMMENT' , $match[0 ]]; } }, $input ); preg_replace_callback_array( [ '~\$[a-z_][a-z\d_]*~i' => function ($match ) use (&$tokenStream ) { $tokenStream[] = ['T_VARIABLE' , $match[0 ]]; }, '~=~' => function ($match ) use (&$tokenStream ) { $tokenStream[] = ['T_ASSIGN' , $match[0 ]]; }, '~[\d]+~' => function ($match ) use (&$tokenStream ) { $tokenStream[] = ['T_NUM' , $match[0 ]]; }, '~;~' => function ($match ) use (&$tokenStream ) { $tokenStream[] = ['T_TERMINATE_STMT' , $match[0 ]]; }, '~//.*~' => function ($match ) use (&$tokenStream ) { $tokenStream[] = ['T_COMMENT' , $match[0 ]]; } ], $input );
<?php $bytes = random_bytes(5 ); var_dump(bin2hex($bytes)); var_dump(random_int(100 , 999 )); var_dump(random_int(-1000 , 0 ));
1.18 define 支持定义数组 <?php define('ALLOWED_IMAGE_EXTENSIONS' , ['jpg' , 'jpeg' , 'gif' , 'png' ]);
查看所有新特性详情
2、PHP7.0.x 新变化
2.1 错误和异常处理相关的变更 在PHP7 中,很多致命错误以及可恢复的致命错误,都被转换为异常来处理了。 这些异常继承自 Error 类,此类实现了 Throwable 接口 (所有异常都实现了这个基础接口)。
这也意味着,当发生错误的时候,以前代码中的一些错误处理的代码将无法被触发。 因为在 PHP7 版本中,已经使用抛出异常的错误处理机制了。(如果代码中没有捕获 Error 异常,那么会引发致命错误)
set_exception_handler() 不再保证收到的一定是 Exception 对象
抛出Error对象时,如果set_exception_handler()里的异常处理代码声明了类型 Exception ,将会导致fatal error。 想要异常处理器同时支持PHP5和PHP7,应该删掉异常处理器里的类型声明。如果代码仅仅是升级到PHP7,则可以把类型 Exception替换成Throwable
<?php function handler (Exception $e ) { ... } set_exception_handler('handler' );function handler ($e ) { ... }function handler (Throwable $e ) { ... }?>
2.2 list() 会按照原来的顺序进行赋值。不再是逆序了
list ($a,$b,$c) = [1 ,2 ,3 ]; var_dump($a); var_dump($b); var_dump($c); var_dump($a); var_dump($b); var_dump($c);
空的list()赋值支持已经被移除 list() 结构现在不再能是空的。如下的例子不再被允许:
<?php list () = $a;list (,,) = $a;list ($x, list (), $y) = $a;
2.3 foreach不再改变内部数组指针 在PHP7之前,当数组通过 foreach 迭代时,数组指针会移动。现在开始,不再如此,见下面代码
<?php $array = [0 , 1 , 2 ];foreach ($array as &$val) { var_dump(current($array)); }int (1 );int (2 );bool (false );int (0 );int (0 );int (0 );
2.4 十六进制字符串不再被认为是数字
含十六进制字符串不再被认为是数字
<?php var_dump(is_numeric("0x123" ));bool (true );bool (false );
查看所有变化详情
3、PHP7.0.x 废弃的特性
3.1 PHP4风格的构造函数(方法名和类名一样)将被弃用,并在将来移除。
PHP4 风格的构造函数(方法名和类名一样)将被弃用,并在将来移除。 如果在类中仅使用了 PHP4 风格的构造函数,PHP7 会产生 E_DEPRECATED 警告。 如果还定义了 __construct() 方法则不受影响。
<?php class foo { function foo ( ) { echo 'I am the constructor' ; } }
以上例程会输出: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in example.php on line 3
3.2 静态调用非静态的方法 废弃了 静态(Static) 调用未声明成 static 的方法,未来可能会彻底移除该功能。
<?php class foo { function bar ( ) { echo 'I am not static!' ; } } foo::bar();
以上例程会输出: Deprecated: Non-static method foo::bar() should not be called statically in - on line 8 I am not static!
查看更多PHP7.0.x 弃用的功能
4、PHP7.0.x 移除的扩展和 SAPI
4.1 移除的扩展
ereg
mssql
mysql
sybase_ct
4.2 移除的 SAPI
aolserver
apache
apache_hooks
apache2filter
caudium
continuity
isapi
milter
nsapi
phttpd
pi3web
roxen
thttpd
tux
webjames
二.PHP7.0.x 移植PHP7.1.x 1、PHP7.1.x 新特性
1.1 可为空(Nullables)类型 参数以及返回值的类型现在可以通过在类型前加上一个问号使之允许为空。 当启用这个特性时,传入的参数或者函数返回的结果要么是给定的类型,要么是null 。
<?php function test (?string $name ) { var_dump($name); } test('elePHPant' ); test(null ); test();
输出结果
string (10 ) "elePHPant" NULL Uncaught Error: Too few arguments to function test (), 0 passed in ...
1.2 Void 函数 一个新的返回值类型void被引入。 返回值声明为 void 类型的方法要么干脆省去 return 语句,要么使用一个空的 return 语句。 对于 void 函数来说,NULL 不是一个合法的返回值
<?php function 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);
输出结果
试图去获取一个 void 方法的返回值会得到 NULL ,并且不会产生任何警告。这么做的原因是不想影响更高层次的方法。
1.3 类常量可见性 现在起支持设置类常量的可见性(public、protected、private)。
<?php class ConstDemo { const PUBLIC_CONST_A = 1 ; public const PUBLIC_CONST_B = 2 ; protected const PROTECTED_CONST = 3 ; private const PRIVATE_CONST = 4 ; }
1.4 短数组语法([]) 短数组语法([])现在作为list()语法的一个备选项,可以用于将数组的值赋给一些变量(包括在foreach中)。
<?php $data = [ [1 , 'Tom' ], [2 , 'Fred' ], ];list ($id1, $name1) = $data[0 ]; [$id1, $name1] = $data[0 ];foreach ($data as list ($id, $name)) { }foreach ($data as [$id, $name]) { }
1.5 iterable伪类 现在引入了一个新的被称为iterable的伪类 (与callable 类似)。 这可以被用在参数或者返回值类型中,它代表接受数组或者实现了Traversable接口的对象。 至于子类,当用作参数时,子类可以收紧父类的iterable类型到array 或一个实现了Traversable的对象。对于返回值,子类可以拓宽父类的 array或对象返回值类型到iterable。
<?php function iterator (iterable $iter ) { foreach ($iter as $val) { } }
1.6 多异常捕获处理 一个catch语句块现在可以通过管道字符(|)来实现多个异常的捕获。 这对于需要同时处理来自不同类的不同异常时很有用。
<?php try { } catch (FirstException | SecondException $e) { }
1.7 list支持键名 现在list()和它的新的[]语法支持在它内部去指定键名。这意味着它可以将任意类型的数组 都赋值给一些变量(与短数组语法类似)
<?php $data = [ ["id" => 1 , "name" => 'Tom' ], ["id" => 2 , "name" => 'Fred' ], ];list ("id" => $id1, "name" => $name1) = $data[0 ]; ["id" => $id1, "name" => $name1] = $data[0 ];foreach ($data as list ("id" => $id, "name" => $name)) { }foreach ($data as ["id" => $id, "name" => $name]) { }
1.8 支持为负的字符串偏移量 现在所有支持偏移量的字符串操作函数 都支持接受负数作为偏移量,包括通过[]或{}操作字符串下标。在这种情况下,一个负数的偏移量会被理解为一个从字符串结尾开始的偏移量。
<?php var_dump("abcdef" [-2 ]); var_dump(strpos("aabbcc" , "b" , -3 )); $string = 'bar' ;echo "The last character of '$string' is '$string[-1]'.\n" ;
1.9 将callables转为闭包 Closure 新增了一个静态方法fromCallable(),用于将callable快速地 转为一个Closure 对象。
<?php class Test { public function exposeFunction ( ) { return Closure ::fromCallable([$this , 'privateFunction' ]); } private function privateFunction ($param ) { var_dump($param); } } $privFunc = (new Test)->exposeFunction(); $privFunc('some value' );
1.10 http2服务推送
对服务器推送的支持现在已经被加入到CURL扩展中( 需要版本 7.46 或更高)。这个可以通过curl_multi_setopt() 函数与新的常量 CURLMOPT_PUSHFUNCTION 来进行调节。常量 CURL_PUST_OK 和 CURL_PUSH_DENY 也已经被添加进来,以便服务器推送的回调函数来表明自己会同意或拒绝处理。
2、PHP7.1.x 新变化
2.1 传递参数过少时将抛出错误
过去我们传递参数过少会产生warning。php7.1开始会抛出error
3、PHP 7.1.x 中废弃的特性
3.1 移除了ext/mcrypt拓展
mcrypt 扩展已经过时了大约10年,并且用起来很复杂。因此它被废弃并且被 OpenSSL 所取代。 从PHP7.2起它将被从核心代码中移除并且移到PECL中。
三.PHP7.1.x 移植PHP7.2.x 1、PHP7.2.x 新特性
1.1 增加新的类型object 这种新的对象类型, object, 引进了可用于逆变(contravariant)参数输入和协变(covariant)返回任何对象类型。
<?php function test (object $obj ) : object { return new SplQueue (); } test(new StdClass ());
1.2 通过名称加载扩展 扩展文件不再需要通过文件加载 (Unix下以.so为文件扩展名,在Windows下以 .dll 为文件扩展名) 进行指定。可以在php.ini配置文件进行启用, 也可以使用 dl() 函数进行启用。
extension =php-astzend_extension =opcache
1.3 允许重写抽象方法 当一个抽象类继承于另外一个抽象类的时候,继承后的抽象类可以重写被继承的抽象类的抽象方法
<?php abstract class A { abstract function test (string $s ) ; }abstract class B extends A { abstract function test ($s ) : int ; }
1.4 使用Argon2算法生成密码散列 Argon2 已经被加入到密码散列(password hashing) API (这些函数以 password_ 开头 ) 以下是暴露出来的常量:`
PASSWORD_ARGON2I
PASSWORD_ARGON2_DEFAULT_MEMORY_COST
PASSWORD_ARGON2_DEFAULT_TIME_COST
PASSWORD_ARGON2_DEFAULT_THREADS
1.5 新增 ext/PDO(PDO扩展) 字符串扩展类型 ¶ 当你准备支持多语言字符集,PDO的字符串类型已经扩展支持国际化的字符集。以下是扩展的常量:
PDO::PARAM_STR_NATL
PDO::PARAM_STR_CHAR
PDO::ATTR_DEFAULT_STR_PARAM
这些常量通过PDO::PARAM_STR利用位运算OR进行计算:
<?php $db->quote('über' , PDO::PARAM_STR | PDO::PARAM_STR_NATL);
1.5 允许分组命名空间的尾部逗号 命名空间可以在PHP7.2中使用尾随逗号进行分组引入。
<?php use Foo \Bar \{ Foo , Bar , Baz , };
在php7.0中 最后一个(Baz,)不能有逗号否则报错
2、PHP7.2.x 新变化
<?php var_dump(number_format(-0.01 ));
<?php var_dump(get_class(null ));
2.3 count 作用在不是 Countable Types 将发生warning
<?php var_dump( count(null ), count(1 ), count('abc' ), count(new stdclass ), count([1 ,2 ]) );
以上例程会输出:
Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d int(0) int(1) int(1) int(1) int(2)
2.4 不带引号的字符串 在之前不带引号的字符串是不存在的全局常量,转化成他们自身的字符串。现在将会产生waring。
is_object 作用在__PHP_Incomplete_Class 将返回:truePreviously, using is_object() on the __PHP_Incomplete_Class class would return FALSE. Now, TRUE will be returned.
gettype作用在闭包在将正确返回resourcePreviously, using gettype() on a closed resource would return a string of "unknown type". Now, a string of "resource (closed)" will be returned.
3、PHP7.2.x 废弃的特性