当前位置: 首页 > news >正文

一篇文章了解php7和php8新特性

PHP7新特性


?? 运算符

php7以前用三目判断变量是否存在或是否为空

$a = isset($_GET['a']) ? $_GET['a'] : 1;

php7新增null 合并运算符??快捷判断

$a = $_GET['a'] ?? 1;

函数返回值类型声明

:+返回值类型的形式定义函数的返回值类型

<?phpdeclare(strict_types=1);
function foo($a) : int
{return $a;
}

不过这里也有一个特点需要注意。PHP 7 增加了一个 declare 指令:strict_types,既使用严格模式。

使用返回值类型声明时,如果没有声明为严格模式,如果返回值不是预期的类型,PHP 还是会对其进行强制类型转换。但是如果是严格模式, 则会出发一个 TypeError 的 Fatal error,跟 js 的 strict mode有点类似

标量类型声明

新增了 stringintfloatbool等类型的的形式参数类型声明,在 PHP 5 中只能是类名、接口、array 或者 callable,例如下面的函数中定义int类型的参数$a

function foo(int $a) : int
{return $a;
}

不过还是要在开启严格模式下才会触发错误,否则php还是会对不符合预期的参数进行强制类型转换,严格模式下则触发 TypeError 的致命错误

use 批量声明

PHP 7 中 use 可以在一句话中声明多个类、函数或 const 了

<?php 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};

太空船运算符

也被称为组合比较运算符或三向比较运算符。这个运算符的符号是 <=>

太空船运算符用于比较两个表达式。它会返回一个整数,表示这两个表达式的相对顺序:

  • 如果左边的值小于右边的值,返回 -1
  • 如果左边的值等于右边的值,返回 0
  • 如果左边的值大于右边的值,返回 1

这使得在需要对两个值进行比较并得到一个明确的排序结果时非常有用,特别是在排序算法中。

示例:

$a = 5;
$b = 10;$result = $a <=> $b;if ($result === -1) {echo "$a is less than $b";
} elseif ($result === 0) {echo "$a is equal to $b";
} else {echo "$a is greater than $b";
}

输出:

csharp5 is less than 10

这种运算符在某些情况下可以使代码更加简洁和易读,特别是当需要进行连续的比较和赋值操作时。

常量数组

在 PHP 7 中,您可以直接在定义常量时定义常量数组。这是通过使用 define() 函数来完成的,其中第一个参数是常量的名称,第二个参数是要分配给该常量的值。对于数组常量,您需要将数组值作为第二个参数传递,并使用 true 作为第三个参数,以指示该常量是一个数组常量。

以下是如何在 PHP 7 中定义和使用常量数组的示例

// 定义常量数组
define('MY_CONSTANT_ARRAY', [1, 2, 3, 4, 5], true);// 检查常量是否已定义
if (defined('MY_CONSTANT_ARRAY')) {// 使用常量数组$array = MY_CONSTANT_ARRAY;print_r($array);
} else {echo "常量 MY_CONSTANT_ARRAY 未定义。";
}

一旦常量被定义,它的值就不能被改变。尝试更改常量的值将收到一个错误,类似于 “Cannot redefine constant MY_CONSTANT_ARRAY”,这意味着可以定义一个不可改变的数组,从而提高代码的可读性和安全性。

匿名类

匿名类允许你创建没有显式类名的临时类,它们通常用于需要一个简单的一次性对象,而不需要定义完整的类。匿名类特别适用于需要实现某个接口或扩展某个类的简单场景,而不必编写额外的类定义。示例:

// 使用匿名类扩展现有类
class BaseClass {public function showMessage() {echo "Hello from BaseClass!";}
}$extendedObj = new BaseClass();
$extendedObj->showMessage(); // 输出 "Hello from BaseClass!"// 使用匿名类扩展 BaseClass
$extendedObj = new class($extendedObj) extends BaseClass {public function showMessage() {parent::showMessage(); // 调用父类的 showMessage 方法echo " and also from the anonymous child class!";}
};$extendedObj->showMessage(); // 输出 "Hello from BaseClass! and also from the anonymous child class!"

匿名类可以包含属性、方法,以及实现接口或扩展类的要求。由于它们是匿名的,你不能在其他地方引用它们,只能在创建它们的上下文中使用它们。这使得它们非常适合于一次性任务,如临时替换某个类的行为,或者在不需要持久化类定义的情况下进行测试。

异常处理改进

在 PHP 7 中,异常处理得到了几个重要的改进,使得处理异常更加简洁、高效和灵活。以下是 PHP 7 中关于异常处理的一些主要改进:

  1. 类型化异常:在 PHP 7 之前,异常通常只是普通的对象,而在 PHP 7 中,你可以使用类名来指定一个异常的类型。这允许你更加精确地捕获特定类型的异常,而不是使用通用的 Exception 类。例如:

    try {// 可能抛出特定类型的异常
    } catch (MyCustomException $e) {// 只处理 MyCustomException 类型的异常
    }
    
  2. 异常链:在 PHP 7 之前,一个异常不能包含另一个异常。在 PHP 7 中,引入了异常链的概念,允许一个异常封装另一个异常,类似于其他语言中的嵌套异常。这有助于保留原始异常的上下文,并允许更详细的错误调试。

    try {// 尝试执行可能出错的代码
    } catch (Exception $e) {throw new MyCustomException("Something went wrong", 0, $e);
    }
    

    在这个例子中,MyCustomException 可以访问原始异常 $e 的所有信息。

  3. finally 块:在 PHP 7 之前,try-catch 结构没有 finally 块,这意味着无论是否发生异常,一些清理代码可能需要在 trycatch 块中重复。在 PHP 7 中,finally 块被引入,它包含了无论是否捕获到异常都需要执行的代码。

    try {// 尝试执行代码
    } catch (Exception $e) {// 处理异常
    } finally {// 无论是否发生异常,都会执行这里的代码
    }
    
  4. 异常接口的变化Exception 接口在 PHP 7 中发生了变化,引入了更多的方法,如 getStringRepresentation(),该方法返回异常的字符串表示形式。同时,Throwable 接口被引入,它是一个所有可被抛出的异常的基类,包括 ExceptionError

  5. 错误和异常的统一处理:PHP 7 引入了 Throwable 接口,它允许你统一处理错误(Error)和异常(Exception)。这意味着你可以在一个 catch 块中同时捕获错误和异常,尽管在实践中通常建议分开处理它们。

这些改进使得 PHP 的异常处理更加成熟和灵活,帮助开发者编写更加健壮和易于维护的代码。

性能优化

性能优化。PHP7 引入了全新的引擎:Zend Engine 3.0,大幅提高了解释和执行 PHP 代码的速度。相比于 PHP 5.x,PHP7 的性能提升了 2-3 倍。

PHP8新特性


JIT编译器

PHP 8 引入了 JIT (Just-In-Time)编译器(即时编译引擎),可以显著提高代码执行速度。JIT编译器已经集成在了Opcache插件中,只有启动Opcache插件才有效;

开启方法:

1.在php.ini文件中添加opcache配置,根据需要调整参数值

[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=128M
opcache.jit=1255

2.将php.ini这行的注释取消

;zend_extension=opcache  #删除前面的;号

3.重启php,在phpinfo()中查看

或者打印变量,查看on的值是否为true

<?php
var_dump(opcache_get_status()['jit']);

注意事项:如果开启了opcache并且修改了代码,那么你需要重启php服务你修改的代码才会生效!!!

命名参数

命名参数允许你在函数调用时明确指定参数的值,而不需要按照函数定义中的参数顺序传递参数。这可以提高代码的可读性和可维护性,特别是在处理具有多个可选参数的函数时。

要使用命名参数,你需要在函数调用时使用参数名称来指定参数的值。参数名称和值之间使用冒号(:)进行分隔。以下是一个示例

<?php
function createUser($name, $age=18, $email, $password = 'password123') {echo $name, $age=18, $email, $password = 'password123';
}// 使用命名参数调用函数,只指定 $name 和 $email
createUser(name: 'John', email: 'john@example.com'); // 使用 $age 的默认值 18 和 $password 的默认值 'password123'

联合类型

联合类型允许一个变量、函数或方法的参数和返回值接受多种不同的类型。这增加了类型系统的灵活性,并有助于在开发过程中提供更准确的类型检查。

联合类型使用竖线(|)分隔多个类型,表示变量、参数或返回值可以是这些类型中的任何一个。以下是一些使用联合类型的示例:

// 变量声明
$variable = 'hello'; // string 类型
$variable = 42; // int 类型
$variable = 4.2; // float 类型
$variable = true; // bool 类型
$variable = null; // null 类型// 函数参数
function processValue(mixed $value): void {// 处理 $value,它可以是任何类型
}// 方法返回值
class Example {public function getValue(): int|float {// 返回 int 或 float 类型的值}
}// 类属性
class User {public function __construct(private string|int $id) {// 构造函数接受 string 或 int 类型的 $id}
}// 类型断言
$value = '42';
if ($value is int|float) {echo "The value is an integer or a float.";
}

联合类型不会改变变量的实际类型,它们只是提供了一种方式来描述变量可能持有的多种类型。在运行时,变量的实际类型仍然是确定的,并且可以通过类型断言或其他方式来检查和操作。

属性改进

  1. 属性初始化: 在 PHP 8 之前,类的属性必须在构造函数中进行初始化。然而,在 PHP 8 中,你可以直接在属性声明时为其赋予默认值,这样就不需要再在构造函数中进行初始化。

    class MyClass {public $myProperty = 'default value'; // 直接在属性声明时初始化
    }
    
  2. 属性类型声明: PHP 8 引入了更严格的类型系统,允许你在属性声明时指定其类型。这有助于在开发过程中捕获类型错误,并提高代码的可读性和可维护性。

    class MyClass {public int $myIntProperty; // 指定属性类型为 int
    }
    
  3. 只读属性
    PHP 8 引入了只读属性(read-only properties)的概念。使用 public readonly 关键字定义的属性只能在对象构造时或在 __construct 方法内部被赋值,之后就不能再修改了。这有助于确保对象的不变性。

    class MyClass {private $myProperty;public function __construct() {$this->myProperty = 'secret';}public function revealProperty(): string {return $this->myProperty; // 传统的 getter 方法}
    }$obj = new MyClass();
    echo $obj->revealProperty(); // 输出 "secret"// 在 PHP 8 中,你也可以这样直接读取私有属性的值(不推荐,因为破坏了封装性)
    echo $obj->myProperty; // 输出 "secret"
    

match表达式

match 表达式允许你根据表达式的值来匹配不同的情况,并执行相应的代码块。它使用了一种类似于数组解构的语法,使得代码更加简洁和直观。

下面是一个使用 match 表达式的示例:

$number = 5;$result = match ($number) {1, 2, 3 => 'Low',4, 5, 6 => 'Medium',7, 8, 9 => 'High',default => 'Unknown',
};echo $result; // 输出 "Medium"

match 表达式的语法比传统的 switch 语句更加简洁,并且支持多个值匹配同一个结果,这使得代码更加易读和易于维护。

需要注意的是,match 表达式在 PHP 8 中是作为一种表达式存在的,它会返回一个值,而不是像 switch 语句那样仅仅执行代码块。因此,你可以将 match 表达式的结果赋值给一个变量,或者在更大的表达式中使用它。

Nullsafe 运算符

在 PHP 8 中,引入了一个新的运算符叫做 Nullsafe 运算符(?->)。这个运算符提供了一种安全的方式来访问对象的属性或调用对象的方法,而不需要担心对象本身是否为 null。在 PHP8以前的版本 中,如果你尝试访问一个 null 对象的属性或方法,将会引发一个错误。为了避免这种情况,开发者通常需要在使用对象之前进行空值检查。然而,这会导致代码变得冗长且难以阅读。

Nullsafe 运算符的引入解决了这个问题。它允许你在不进行显式空值检查的情况下安全地访问对象的属性或方法。如果对象本身是 null,Nullsafe 运算符将返回 null,而不会引发错误。

class User {public $name;public function getName() {return $this->name;}
}$user = null;// 使用传统的方式访问属性或方法会引发错误
// echo $user->name; // Error: Trying to get property 'name' of non-object
// echo $user->getName(); // Error: Calling a member function getName() on null// 使用 Nullsafe 运算符安全地访问属性或方法
echo $user?->name; // 输出 null,而不是引发错误
echo $user?->getName(); // 输出 null,而不是引发错误

字符串与数字的比较

PHP 8 比较数字字符串(numeric string)时,会按数字进行比较。 不是数字字符串时,将数字转化为字符串,按字符串比较。

0 == 'foobar' // php7执行结果为:true
0 == 'foobar' // php8执行结果为:false

构造器属性提升

这个新的语法糖来用来创建值对象或数据传输对象。不用为类属性和构造函数指定它们,PHP 现在可以将它们合并为一个。

php7定义类属性和构造方法赋值:

class Money 
{public Currency $currency;public int $amount;public function __construct(Currency $currency,int $amount,) {$this->currency = $currency;$this->amount = $amount;}
}

php8合并定义类属性和构造方法赋值:

class Money 
{public function __construct(public Currency $currency,public int $amount,) {}
}

其他调整

更多细节调整参考官方文档

PHP: PHP 8.0.0 Release Announcement

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 鸿蒙南向开发:制作【智能儿童手表】
  • java实现API服务及请求客户端
  • Utilize webcam to capture photo with camera
  • Leetcode C语言习题
  • 头歌:共享单车之数据可视化
  • Docker之数据卷和Dockerfile
  • 2024 年最新使用 Wechaty 开源框架搭建部署微信机器人(微信群智能客服案例)
  • 前端二维码工具小程序产品使用说明书
  • RISC-V特权架构 - 模式切换与委托
  • Leetcode 68. 文本左右对齐
  • GFS分布式 文件系统
  • 前端小白的学习之路(Vue2 一)
  • Excel全套213集教程
  • 【数据结构】考研真题攻克与重点知识点剖析 - 第 5 篇:树与二叉树
  • Rust 实现线程安全的 Lock Free 计数器
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【刷算法】求1+2+3+...+n
  • canvas绘制圆角头像
  • CentOS从零开始部署Nodejs项目
  • CSS 专业技巧
  • es6--symbol
  • fetch 从初识到应用
  • HTTP中GET与POST的区别 99%的错误认识
  • Javascript 原型链
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Java小白进阶笔记(3)-初级面向对象
  • magento 货币换算
  • MySQL-事务管理(基础)
  • React Transition Group -- Transition 组件
  • scala基础语法(二)
  • 大型网站性能监测、分析与优化常见问题QA
  • 给初学者:JavaScript 中数组操作注意点
  • 汉诺塔算法
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 开源地图数据可视化库——mapnik
  • 前端技术周刊 2019-02-11 Serverless
  • 我感觉这是史上最牛的防sql注入方法类
  • 我与Jetbrains的这些年
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • postgresql行列转换函数
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • ​第20课 在Android Native开发中加入新的C++类
  • ​批处理文件中的errorlevel用法
  • # 飞书APP集成平台-数字化落地
  • #Z2294. 打印树的直径
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (42)STM32——LCD显示屏实验笔记
  • (C++20) consteval立即函数
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (ibm)Java 语言的 XPath API