美文网首页
PHP5.5到PHP7的新特性

PHP5.5到PHP7的新特性

作者: camellia_halo_ | 来源:发表于2018-11-20 18:36 被阅读0次

    PHP5.5到PHP7的新特性

    作者:悟尘

    一、PHP5.5

    官方手册:http://php.net/manual/zh/migration55.new-features.php

    PHP 5.5.x 中废弃的特性

    废弃 ext/mysql

    原始的 MySQL 扩展 现在被废弃,当连接到数据库时会产生一个 E_DEPRECATED 错误。可使用 MySQLi 或PDO_MySQL 扩展作为替代。

    preg_replace() 中的 /e 修饰符 eval

    preg_replace() 函数中用到的 /e 修饰符现在被弃用。可以使用 preg_replace_callback() 函数来替代。

    但是如果你非要用,它还可以支持的,最高支持以php5.6.x,不过会报Deprecated,PHP7中就不可以使用了.

    PHP 5.5.x 中新特性:

    1、生成器[yield]

    关键点 : [yield]它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并终止函数的执行,而yield会返回一个值给调用此生成器的代码,并且只是执行生成器函数 循环

    <?php

    $html = '<h1>hello world</h1>';

    $html = preg_replace(

    '(<h([1-6])>(.*?)</h\1>)e',

    '"<h$1>" . strtoupper("$2") . "</h$1>"',$html);

    $html = '<h1>hello world</h1>';

    $html = preg_replace_callback('(<h([1-6])>(.*?)</h\1>)',function ($m) {return "<h$m[1]>" . strtoupper($m[2]) . "</h$m[1]>";},$html);

    <?php

    echo '<pre>';

    function fun(){

    yield 1;

    yield 2;

    yield 3;

    yield 4;

    yield 5;

    // 我们可以使用echo来进行输出

    //echo 'ok';

    }

    $ret = fun();

    foreach($ret as $item){

    echo $item.'<hr>';

    }

    // 传统的循环数据中的数据

    $arr = range(1,10);

    foreach(range(1,10) as $val){

    echo $val.'<hr>';

    }

    // 运用生成器来生成1到10的记录数

    function xrange(){

    for($i = 1; $ <= 10; $i++){

    yield $i;

    }

    }

    // 循环读取出生成器中的内容

    foreach(xrange() as $item){echo $item.'<hr>';}

    // 数据库操作

    $dsn = 'mysql:host=localhost;dbname=a67_web64;charset=utf8';

    $user = 'root';

    $pwd = 'root';

    try{

    $pdo = new PDO($dsn, $user, $pwd);

    }catch (PDOException $e){

    throw new Exception($e->getMessage());

    }

    $sql = "select * from a67_addon_dianying";

    echo '<pre>';

    foreach(findAll($sql) as $item){

    extract($item);

    echo $aid.'----'.$daoyan.'<hr>';

    }

    2、finally关键字的使用

    不管抛出异常是否被抛出,程序代码块都会被执行

    注: finally区块中一般执行一些如关闭资源和连接等操作,此代码块不管程序是否有异常都必须要执行。

    3、foreach 现在支持 list()

    foreach 控制结构现在支持通过 list() 构造将嵌套数组分离到单独的变量

    function findAll($sql){

    global $pdo;

    $stmt = $pdo->prepare($sql);

    $stmt->execute();

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){

    yield $row;

    }

    }

    <?php

    try {

    // 抛出异常消息

    throw new Exception('打开文件失败');

    } catch (Exception $e) {

    // 处理异常错误

    echo '<pre>';

    var_dump($e);

    // 模拟可以处理异常的时候出现了别的异常情况的情况

    throw new Exception('处理异常失败');

    }finally{

    // 无论如何都要执行此代码块中的内容

    echo '<br>文件我关闭了';

    }

    echo '<br>看我执行了没有了';

    <?php

    // 定义一个数组

    $arr = [

    [1,2],

    [3,4],

    [5,6],

    ];

    // 需求,把上面的数组打印出来

    // 以前的写法

    foreach($arr as $val){

    echo $val[0].' -- '.$val[1].'<hr>';

    }

    // php5.5以后的写法 foreach中支持 list写法 支持索引数组

    foreach($arr as list($a,$b)){

    echo $a.' -- '.$b.'<hr>';

    }

    #注: 关联数组暂不支持

    4、empty() 支持任意表达式

    empty() 现在支持传入一个任意表达式,而不仅是一个变量,对以前的功能的升级

    <?php

    echo '<pre>';

    // 定义一个函数

    function fun(){

    return true;

    }

    // 空字符串

    var_dump(empty('')); # true

    // 支持表达式

    var_dump(empty(1 + 2)); # false

    var_dump(empty(1 + 1 > 3)); # true

    // 支持调用函数

    var_dump(empty(fun())); # false

    5、新的密码加密函数-password_hash()

    简单的md5加密很容易通过字典的方式进行破解,随便找个md5解密的网站就能获取原始密码,所以PHP官方推出了一个新的加密的函数,password_hash。

    password_hash加密

    优点:就是更加的安全可靠,每次运行加密的结果都不一致。

    缺点:互操作性差,如和其它语言进行交互验证加密起来就不行了,只能通过password_verify来验证。

    string password_hash ( string $password , integer $algo [, array $options ] )

    当前支持的算法:

    PASSWORD_DEFAULT - 使用 bcrypt 算法 (PHP 5.5.0 默认)。 注意,该常量会随着 PHP 加入更新更高强度的算法而改变。 所以,使用此常量生成结果的长度将在未来有变化。 因此,数据库里储存结果的列可超过60个字符(最好是255个字符)。

    PASSWORD_BCRYPT - 使用 CRYPT_BLOWFISH 算法创建哈希。 这会产生兼容使用 " 2y" 的 crypt()。结果将会是 60 个字符的字符串, 或者在失败时返回 FALSE。

    ①、加密 password_hash

    <?php

    // 明文密码

    $pwd = 'admin888';

    // 加密密码

    echo password_hash($pwd,PASSWORD_DEFAULT);

    ②、验证 password_verify

    password_verify() 验证密码是否和哈希匹配

    boolean password_verify ( string $password , string $hash )

    $password 明文的密码

    $hash 加密的密码

    <?php

    // 明文密码

    $pwd = 'admin888';

    // 加密密码

    $pass = password_hash($pwd,PASSWORD_DEFAULT);

    echo '加密后的密码:'.$pass.'<hr>';

    // 验证密码是否正确

    // 不正确

    $plainPwd = '111';

    if (password_verify($plainPwd,$pass)) {

    echo '密码一致<hr>';

    }else{

    echo '密码不一致<hr>';

    }

    // 正确

    if (password_verify($pwd,$pass)) {

    echo '密码一致<hr>';

    }else{

    echo '密码不一致<hr>';

    }

    二、PHP5.6

    官方手册:http://php.net/manual/zh/migration56.new-features.php

    PHP 5.6.x 中已废弃的特性

    $HTTP_RAW_POST_DATA 和 always_populate_raw_post_data

    使用 always_populate_raw_post_data 会导致在填充 HTTP_RAW_POST_DATA 时产生 E_DEPRECATED 错误。

    请使用 php://input 替代 HTTP_RAW_POST_DATA, 因为它可能在后续的 PHP 版本中被移除。

    设置 always_populate_raw_post_data 为 -1 (这样会强制 $HTTP_RAW_POST_DATA 未定义,所以也不会导致E_DEPRECATED 的错误) 来体验新的行为。

    1、使用表达式定义常量 const

    http://blog.csdn.net/cscrazybing/article/details/46989749

    // 1、const不能放在循环或条件语句中,只放在命名空间或头档的顶级中,则可以

    // 2、在类中定义常量,只能用const

    // 3、define在php7之前不能定义数组而const则可以

    // 4、const在php5.6之前是不可定义表达式常量,define则可以

    <?php

    const ONE = 1;

    const TWO = ONE * 2;

    class C {

    const THREE = TWO + 1;

    const ONE_THIRD = ONE / self::THREE;

    const SENTENCE = 'The value of THREE is '.self::THREE;

    public function f($a = ONE + self::THREE) {

    return $a;

    }

    }

    echo (new C)->f()."<hr>";

    echo C::SENTENCE;

    2、使用 ... 运算符定义变长参数函数和参数展开

    <?php

    echo '<pre>';

    // 把第三个以一的参数全部在函数中接收

    function test($a,$b,...$c){

    // 前两个参数给了$a和$b

    echo $a.'---'.$b.'<br>';

    // 后面的全部以一维数组的形式给了$c

    print_r($c);

    }

    test(1,2,3,4,5,6,7);

    echo '<hr>';

    // 使用 ... 运算符进行参数展开

    $arr = [1,2,3,4,5];

    test(...$arr);

    3、导入命令空间中的常量和函数

    对use运算符进行了扩展以支持在类中导入外部的函数和常量。对应的结构为 use function 和 use const

    <?php

    // 申明一个A命名空间

    namespace A {

    const AGE = 20;

    function fun(){

    echo "<hr>你好!";

    }

    }

    // 申明一个B命名空间

    namespace B {

    // 调用 命名空间A中的常量和函数 使用use

    use const A\AGE;

    use function A\fun;

    echo '<pre>';

    var_dump(AGE);

    fun();

    }

    三、PHP7.0

    官网手册:http://php.net/manual/zh/migration70.new-features.php

    解析顺序的变化

    表达式                    PHP 5 的解析方式              PHP 7 的解析方式

    $$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']

    $foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']

    $foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']()

    Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()

    所有 ext/mysql 函数已被删掉了

    移除掉的 INI 配置指令

    always_populate_raw_post_data 在php.ini文件中已经移除

    always_populate_raw_post_data 只能用file_get_content('php://input')

    要想在php5.6之前生效,还需要打开工php.ini中的配置文件 asp_tags = Off修改为 asp_tags = On 然后重启apache,此选项在php7之后被移除

    asp_tags <%=$name;%>

    1、标量类型声明[严格类型]

    标量的类型的申明有两种模式:强制(默认)和严格模式。

    字符串 string

    布尔值 bool

    整数 int

    浮点 float

    类[class]、接口[interface]、回调[callable]

    ①、强制模式[默认]

    <?php

    function test(array $arr){

    echo '<pre>';

    var_dump($arr);

    }

    #test(1); // 报错

    test([1,2,3]);

    ②、严格模式

    默认情况下,如果能做到的话,PHP将会强迫错误类型的值转为函数期望的标量类型。 例如,一个函数的一个参数期望是string,但传入的是integer,最终函数得到的将会是一个string类型的值。

    可以基于每一个文件开启严格模式。在严格模式中,只有一个与类型声明完全相符的变量才会被接受,否则将会抛出一个TypeError。 唯一的一个例外是可以将integer传给一个期望float的函数。

    开启严格模式

    使用 declare 语句和strict_types 声明来启用严格模式,声明指令必须放在文件的顶部,意味着严格声明标量是基于文件可配的, 这个指令不仅影响参数的类型声明,也影响到函数的返回值声明。

    <?php

    # 开启严格模式

    declare(strict_types=1);

    function test2(string $username,int $age){

    echo '名称:'.$username;

    echo '<br>';

    echo '年龄:'.$age;

    }

    #test(1,20); # 报错

    test2('小明',20);

    2、返回值类型声明

    返回类型声明指明了函数返回值的类型,类型有class,interface,array,int,callable,bool,float,int,string

    <?php

    # 开启严格模式

    declare(strict_types=1);

    // 返回值类型申明

    function test2(int $age) : bool{

    if ($age >20) {

    return true;

    }else{

    return false;

    }

    }

    if (test2(19)) {

    echo '年龄有点的小';

    }else{

    echo '成年了';

    }

    # 使用它的时候,一定要有memcache扩展

    function sum2(int $a, int $b): Memcache {

    return new Memcache();

    }

    开启类型限定,可以极大的提升PHP在编译阶段对程序的执行速度的优化提升。

    3、null合并运算符[重要]

    简化了之前的三元表达式的写法

    <?php

    // php7.0 之前的写法

    $username = $_GET['username'] ? $_GET['username'] : '没有名称';

    echo $username;

    echo '<hr>';

    // php7.0之后

    $uname = $_GET['uname'] ?? '没有姓名';

    echo $uname;

    echo '<hr>';

    // 嵌套来运用

    $age = $_GET['age'] ?? $_POST['age'] ?? '没有值';

    echo $age;

    4、太空船操作符(组合比较符)

    太空船操作符用于比较两个表达式。当 $a 小于、等于或大于$b时它分别返回-1、0或1

    <?php

    // 比较两个变量的大小,如果a变量大于b变量,返回1

    // 如果a变量等于b变量,返回0

    // 如果a变量小于b变量,返回-1

    function compare($a,$b){

    if ($a > $b) {

    return 1;

    }elseif ($a == $b) {

    return 0;

    }elseif ($a < $b) {

    return -1;

    }

    }

    $a = 1;

    $b = 2;

    var_dump(compare($a,$b));

    echo '<br>';

    $a = 2;

    $b = 2;

    var_dump(compare($a,$b));

    echo '<br>';

    $a = 2;

    $b = 1;

    var_dump(compare($a,$b));

    echo '<hr>';

    // php7.0之后来完成这样的需求

    $a = 1;

    $b = 2;

    var_dump($a <=> $b); # -1

    echo '<br>';

    $a = 2;

    $b = 2;

    var_dump($a <=> $b); # 0

    echo '<br>';

    $a = 2;

    $b = 1;

    var_dump($a <=> $b); # 1

    echo '<hr>';

    注:一定使用的场景多在一些算法场景中,如我们的排序,像【usort】可带回定义回调规则排序中,就可以运用。

    $a = array(3, 2, 5, 6, 1);

    usort($a,function ($v1,$v2){

    return $v1 <=> $v2;

    });

    echo '<pre>';

    print_r($a);

    5、通过 define() 定义常量数组

    <?php

    # 定义一个常量的数组

    define('ADMINS',[

    'admin',

    'zhangsan',

    'lisi',

    [1,2,3]

    ]);

    echo '<pre>';

    print_r(ADMINS);

    echo ADMINS[1];

    6、匿名类

    现在支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。

    <?php

    // 匿名类

    $obj = new class {

    public $username = '小明<hr>';

    public function __construct(){

    echo '这是一个匿名的类<hr>';

    }

    };

    echo $obj->username;

    # 日志接口

    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) {

    return $msg;

    }

    });

    var_dump($app->getLogger());

    echo '<hr>';

    var_dump($app->getLogger()->log('111'));

    7、Unicode 转译语法

    每个汉字都有对应的unicode编码

    PHP是世界上最好的语言

    \u50\u48\u50\u662f\u4e16\u754c\u4e0a\u6700\u597d\u7684\u8bed\u8a00

    <?php

    像这样的编码在php7.0之后可以直接转化为汉字,人可识别的,php7.0之前的PHP的转化可以参考此地址来使用:http://blog.csdn.net/friendan/article/details/52900529

    /**

    * PHP是世界上最好的语言

    * \u50\u48\u50\u662f\u4e16\u754c\u4e0a\u6700\u597d\u7684\u8bed\u8a00

    */

    $unicodeStr =

    "\u{50}\u{48}\u{50}\u{662f}\u{4e16}\u{754c}\u{4e0a}\u{6700}\u{597d}\u{7684}\u{8bed}\u{8a00}";

    echo $unicodeStr;

    注:定义的字符必须用双引号且还必须要用{}括起来不带\u的部份,应用的场景如emoji图标:

    https://unicode-table.com/cn/sets/hearts-symbols/

    8、Closure::call()

    Closure::call() 现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。

    <?php

    # 匿名函数

    $fun2 = function(){

    $this->say();

    };

    class Test {

    private function say(){

    echo 'Hi.<br>';

    }

    }

    $fun2->call(new Test);

    9、预期 assert

    预期是向后兼用并增强之前的 assert() 的方法。 它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。它允许第一个参数是一个表达式,在调试测试中用。

    <?php

    // assert(true|false)

    // 如果为true 得到了预期的结果,后面的结果不能执行

    // 如果为false 没有得到预期的结果,执行后面

    //assert(true,'1111');

    assert(1+1>3 , new Exception('预期失败,异常抛出,条件不成立。'));

    10、批量导入命名空间

    从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入。

    <?php

    namespace A {

    class C1{}

    class C2{}

    function fun1(){echo 'fun1';}

    function fun2(){echo 'fun2';}

    const AGE1 = 20;

    const AGE2 = 21;

    }

    // PHP 7 之前的代码

    namespace B {

    use A\C1;

    use A\C2;

    use function A\fun1;

    use function A\fun2;

    use const A\AGE1;

    use const A\AGE2;

    }

    // PHP 7+ 及更高版本的代码

    namespace C {

    use A\{C1,C2};

    use function A\{fun1,fun2};

    use const A\{AGE1,AGE2};

    var_dump(new C1());

    echo '<hr>';

    var_dump(new C2());

    echo '<hr>';

    fun1();

    echo '<hr>';

    fun2();

    echo '<hr>';

    echo AGE1;

    echo '<hr>';

    echo AGE2;

    echo '<hr>';

    }

    11、生成器[yield]可以返回表达式

    此特性基于 PHP 5.5 版本中引入的生成器特性构建的。 可以通过调用 Generator::getReturn() 方法来获取生成器的返回值, 但是这个方法只能在生成器完成产生工作以后调用一次。

    <?php

    function test(){

    yield '1<br>';

    yield '2<br>';

    yield '3<br>';

    return '我是返回值:4<hr>';

    }

    $gen = test();

    #echo $gen->getReturn(); # 报错,必须是生成循环完毕后才能执行它

    foreach ($gen as $val) {

    echo $val;

    }

    echo $gen->getReturn();

    ## 类JS的写法

    $gen2 = (function() {

    yield '张三';

    yield '李四';

    return '返回值';

    })();

    foreach ($gen2 as $val) {

    echo $val, '<br>';

    }

    echo $gen2->getReturn(), '<hr>';

    四、PHP7.x

    官网手册:http://php.net/manual/zh/migration71.new-features.php

    1、可为空(Nullable)类型

    类型现在允许为空,当启用这个特性时,传入的参数或者函数返回的结果要么是给定的类型,要么是 null 。可以通过在类型前面加上一个问号【?】来使之成为可为空的。

    <?php

    function test(?string $username,int $age){

    echo "姓名:{$username} -- 年龄:{$age}<hr>";

    }

    test('小明',20);

    test(null,22);

    2、 Void函数

    对于 void 函数来说,null 不是一个合法的返回值

    <?php

    # 可以不写return 或 return;就可以,返回null会报错

    function test() : void {

    return; //表示返回void

    echo 111;

    //return null; # 报错,因为return null不能替换return;

    }

    test();

    3、array赋值变量取出

    短数组语法([])现在可以用于将数组的值赋给一些变量(包括在foreach中)。 这种方式使从数组中提取值变得更为容易。

    <?php

    $arr = [1,2];

    [$a,$b] = $arr;

    echo $a.' -- '.$b;

    echo '<hr>';

    // 互换两个变量的值

    $aa = 1;

    $bb = 2;

    [$aa,$bb] = [$bb,$aa];

    echo $aa.' -- '.$bb;

    echo '<hr>';

    // 定义数组

    $data = [

    ['id' => 1,'name' => 'tom'],

    ['id' => 2,'name' => 'jack']

    ];

    // 取出数组中的元素给指定的变量

    ['id' => $id,'name' => $name] = ['id' => 1,'name' => 'tom'];

    echo $id.' --- '.$name.'<br>';

    echo '<hr>';

    // 循环中取出数组中的元素给指定的变量

    foreach($data as ['id' => $id,'name' => $name]){

    echo $id.' --- '.$name.'<br>';

    }

    4、多异常捕获

    一个catch语句块现在可以通过管道字符(|)来实现多个异常的捕获。 这对于需要同时处理来自不同类的不同异常时很有用。

    <?php

    class Exception1 extends Exception {

    }

    class Exception2 extends Exception {

    }

    class Exception3 extends Exception {

    }

    try {

    throw new Exception('这里有异常了');

    } catch (Exception1|Exception2|Exception3 $e) {

    var_dump($e);

    }

    5、list()支持关联数组

    现在list()支持在它内部去指定键名。这意味着它可以将任意类型的数组 都赋值给一些变量(与短数组语法类似)

    <?php

    $arr = ['username' => '张三', 'age' => 20];

    list('username' => $username, 'age' => $age) = $arr;

    echo $username . '----' . $age . '<hr>';

    $data = [

    ['id' => 1, 'name' => 'Tom'],

    ['id' => 2, 'name' => 'jack'],

    ];

    echo '<hr>';

    // php7.1写法

    foreach($data as list('id' => $id, 'name' => $name)){

    echo $id . '----' . $name . '<br>';

    }

    相关文章

      网友评论

          本文标题:PHP5.5到PHP7的新特性

          本文链接:https://www.haomeiwen.com/subject/oxilzftx.html