一篇文章了解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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/815474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法刷题记录 Day46

算法刷题记录 Day46 Date: 2024.04.13 lc 53. 最大子数组和 class Solution { public:int maxSubArray(vector<int>& nums) {// dp[i]表示以nums[i]结尾的连续子数组的最大和&#xff1b;// dp[i] max(nums[i], dp[i-1]nums[i]);若之前的最大和小于0&#xff0c;…

Unity DOTS1.0(4) Baking 和 Baker

Baking 概念&#xff1a; 把Editor中的GameObject数据转换成entities数据写入到Entity Scens里面,这个过程我们叫做BakingBaking是一种不可逆的操作&#xff0c;把低效代价昂贵的但是灵活的GameObjects转换成性能高效的Entities与Components。 作用&#xff1a; 在传统的模…

MyBatis批量插入的五种方式

MyBatis批量插入的五种方式: 一、准备工作 1、导入pom.xml依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MySQL驱动依赖 --…

【蓝桥杯日常】

美丽的2 #include <iostream> using namespace std; int main() {int cnt0; int tmp;for(int i1;i<2020;i){tmpi;//避免改变i的值while(tmp){if(tmp%102){cnt;break;//有2就跳出循环} tmp/10;}}cout<<cnt;return 0; }基础不牢地动山摇是我这样的。这个题花费的…

韩顺平 | 零基础快速学Python(15) 错误和异常

概述 Python有两种不同的错误&#xff1a;语法错误和异常。 语法错误SyntaxError/句法错误/解析错误&#xff1a;执行前编译器检测到的错误。语法错误也是一种异常&#xff0c;SyntaxError继承Exception。 异常Exception&#xff1a;执行时检测到的错误。 需求&#xff1a;出…

vue3 依赖-组件tablepage-vue3说明文档,列表页快速开发,使用思路及范例(Ⅱ)搜索及数据获取配置项

github求⭐ vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例&#xff08;Ⅰ&#xff09;配置项文档 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例&#xff08;Ⅱ&#xff09;搜索…

Linux命令-dris命令(显示和清空目录堆栈中的内容)

说明 dris命令 用于显示和清空目录堆栈中的内容。 语法 dris(选项)选项 n&#xff1a;显示从左边算起第n笔的目录&#xff1b; -n&#xff1a;显示从右边算起第n笔的目录&#xff1b; -l&#xff1a;显示目录完整的记录。

Java 8 Date API:深挖`LocalDate.plusWeeks(1)`方法的使用及潜在“陷阱”

这里写目录标题 引言方法介绍潜在“陷阱”与注意事项1. 对于跨越月份和年份边界的情况2. ISO周定义的影响3. 时间区间的理解和使用 正确使用与规避“陷阱”结语 引言 在Java 8中&#xff0c;日期时间API进行了全面改革&#xff0c;引入了新的java.time包&#xff0c;其中的Loca…

什么是享元模式,有哪些具体应用

一、定义 享元模式是一种通过尽可能多地共享数据来最小化内存使用和对象数量&#xff0c;从而提高性能的设计模式。在享元模式中&#xff0c;如果需要相同数据的多个对象&#xff0c;则共享这些对象而不是创建新的对象&#xff0c;从而提高系统的效率。 其实有很多应用场景&am…

数据库(1)

目录 1.什么是事务&#xff1f;事务的基本特性ACID&#xff1f; 2.数据库中并发一致性问题&#xff1f; 3.数据的隔离等级&#xff1f; 4.ACID靠什么保证的呢&#xff1f; 5.SQL优化的实践经验&#xff1f; 1.什么是事务&#xff1f;事务的基本特性ACID&#xff1f; 事务指…

kotlin基础学习教程以及代码案例

基础概念和知识点&#xff1a; Kotlin的基础语法涵盖了许多重要的知识点&#xff0c;以下是其中的一些核心要素&#xff1a; 变量与常量&#xff1a; var 关键字用于声明可变的变量。val 关键字用于声明只读的变量&#xff0c;即常量。const val 用于编译时常量&#xff0c;只…

Alibaba --- 如何写好 Prompt ?

如何写好 Prompt 提示工程&#xff08;Prompt Engineering&#xff09;是一项通过优化提示词&#xff08;Prompt&#xff09;和生成策略&#xff0c;从而获得更好的模型返回结果的工程技术。总体而言&#xff0c;其实现逻辑如下&#xff1a; &#xff08;注&#xff1a;示例图…

Kotlin - 时间 Duration

一、概念 用于表示时间度量&#xff0c;简化了时间单位的换算、计算时间差、操作间隔、比较等场景。 二、使用 2.1 创建 2.1.1 Number -> Duration 扩展函数适用于 Int、Long、Double。Duration 可以是正、负、零、正无穷大或负无穷大。 nanosecondspublic inline val Int…

napi系列学习进阶篇——NAPI异步调用

简介 OpenHarmony Napi 标准系统异步接口实现支持Callback方式和Promise方式。标准系统异步接口实现规范要求&#xff0c;若引擎开启Promise特性支持&#xff0c;则异步方法必须同时支持Callback方式和Promise方式。使用哪种方式由应用开发者决定&#xff0c;通过是否传递Call…

SpringMVC--获取请求参数 / 域对象共享数据

目录 1. SpringMVC 获取请求参数 1.1. 通过ServletAPI获取 1.2. 控制器方法形参获取 1.3. RequestParam 1.4. RequestHeader 1.5. CookieValue 1.6. 通过POJO获取请求参数 1.7. 解决获取请求参数的乱码问题 2. 域对象共享数据 2.1. 三大域对象 2.2. 准备工作 2.3. S…

RedisTemplate对象中方法的使用

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Redis是一个key-va…

第二届数据安全大赛暨首届“数信杯”数据安全大赛数据安全积分争夺赛-东区预赛wp

附件下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1tClZrup28n4fUe5Kpa7mgQ?pwdkbd6 文章目录 数据安全题re_ds001Homooo0 数据分析题数据分析1-1数据分析1-2数据分析1-3数据分析2-1数据分析2-2数据分析2-3数据分析3-1数据分析3-2数据分析3-3数据分析5-1数据…

【AI基本模型】简化生成对抗网络 (GAN)

目录 一、说明 二、GAN的工作 三、如何手动计算生成对抗网络&#xff08;GAN&#xff09;&#xff1f;✍️ 四、GAN的应用 一、说明 生成对抗网络 &#xff08;GAN&#xff09; 是一种机器学习算法&#xff0c;可以生成与现实世界数据几乎无法区分的合成数据。它们的工作原理是…

【计算机毕业设计】基于Java+SSM的实战开发项目150套(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f9e1;今天给大家分享150的Java毕业设计&#xff0c;基于ssm框架&#xff0c;这些项目都经过精心挑选&#xff0c;涵盖了不同的实战主题和用例&#xff0c;可做毕业设计和课程…

js的filter函数

在JavaScript中&#xff0c;filter() 是一个数组方法&#xff0c;它创建一个新数组&#xff0c;其包含通过提供的函数实现的测试的所有元素。换句话说&#xff0c;filter() 函数遍历数组中的每个元素&#xff0c;并只将那些使测试函数返回 true 的元素包含在新数组中。 这里有…