PHP新特性集合

news2024/11/26 9:06:14

php8新特性

命名参数

function foo(string $a, string $b, ?string $c = null, ?string $d = null) 
{ /* … */ }

你可以通过下面的方式传入参数进行调用

foo(
    b: 'value b', 
    a: 'value a', 
    d: 'value d',
);

联合类型

php7

class Number {
  /** @var int|float */
  private $number;
  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
  }
}
new Number('NaN'); // Ok

php8

class Number {
  public function __construct(
    private int|float $number
  ) {}
}
new Number('NaN'); // TypeError

新的 mixed类型

mixed本身是以下类型之一:

array
bool
callable
int
float
null
object
resource
string
function bar(): ?mixed {} 

nullsafe运算符

//现在可以用新的 nullsafe 运算符链式调用,而不需要条件检查 null。 如果链条中的一个元素失败了,整个链条会中止并认定为 Null。

$country =  null;
if ($session !== null) {
  $user = $session->user;
  if ($user !== null) {
    $address = $user->getAddress();
 
    if ($address !== null) {
      $country = $address->country;
    }
  }
}

//简化为一行代码
$country = $session?->user?->getAddress()?->country;

str_contains()、str_starts_with()和str_ends_with()函数

有些人可能会说它早就该有了,但我们终于不必再依赖strpos() 来知道字符串是否包含另一个字符串了。

//判断$s 中是否存在words
$s = 'string with lots of words';
if (str_contains($s, 'words')) { /* … */ }

str_starts_with('haystack', 'hay'); // true  判断开头
str_ends_with('haystack', 'stack'); // true  判断结尾

WeakMap类

WeakMap是将对象作为key来访问的map。也就是说,WeakMap中的是存储另一个对象的引用,一旦另一个对象被删除,该WeakMap的key的引用也会断开。

不使用WeakMap的案例


<?php
// 房子
class House
{
    public function __construct(public array $rooms = [])
    {
    }

    // 添加人
    public function addPerson(Person $person)
    {
       $this->rooms[$person->name] = $person;
    }
}

// 人
class Person
{
    public function __construct(public string $name)
   {
   }
}


$house = new House();
$lucy = new Person('lucy');
$jony = new Person('jony');

// 为房子添加人
$house->addPerson($lucy);
$house->addPerson($jony);

echo count($house->rooms); // 2人
unset($lucy); // 删除1人
echo count($house->rooms); // 还是2人

// 这个人还在
$lucyObj = $house->rooms['lucy'];
echo $lucyObj->name; // lucy

WeakMap的使用


class House
{
    public WeakMap $rooms;

    public function __construct()
    {
     // 实例化 WeakMap
     $this->rooms = new WeakMap();
    }

    public function addPerson(Person $person)
    {
       // 注意,这里的键一定是要一个对象
     $this->rooms[$person] = $person->name;
    }
}

class Person
{
    public function __construct(public string $name)
   {
   }
}

// 房东
$house = new House();
// 租房的人
$lucy = new Person('lucy');
$jony = new Person('jony');

// 租房并给要钥匙
$house->addPerson($lucy);
$house->addPerson($jony);

// 查看租房人数
echo count($house->rooms); // 2人
// lucy不租了(删除引用)
unset($lucy);
// 再次查看租房人数
echo count($house->rooms); // 1人

$lucyObj = $house->rooms['lucy'];
// 报错,lucy这个人已经走了
print_r($lucyObj);
// 通过调用WeakMap中提供的迭代器方法来查看其他租客信息
foreach ($house->rooms->getIterator() as $k => $v) {
print_r($k);
}

==============php7新特================

标量类型的声明

标量类型声明有两种模式: 强制 (默认) 和 严格模式。 现在可以使用下列类型参数(无论用强制模式还是严格模式): 字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool)。它们扩充了PHP5中引入的其他类型:类名,接口,数组和 回调类型。

PHP标量包含: 字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool)。

php函数接受多个参数

function getNum(){
    $arr = func_get_args(); //获取全部
    print_r(func_get_arg(1)); // 获取第几个参数
    print_r($arr);
}
getNum(1,"qwer",[1,2,3]);
function sumOfInts(int ...$ints)
{
    print_r(func_get_args()); // 获取第几个参数
}

sumOfInts(1,2,3);

返回值类型声明

/**
 *  ?array  表示必须传入数组或者null,否则报错
 *  : ?array 表示返回必须是数组或者null,否则报错
 */
function arraysSum(?array $arrays): ?array
{
    return $arrays;
}
var_dump(arraysSum([6]));
/**
 * @param $s
 * @return string|null
 *  如果输入参数$s 没有限定的话,输入int类型会转换为string,如果数组array类型会报错
 */
function stringTest($s): ?string
{
    return $s;
}
var_dump(stringTest(5));
/**
 * @param int|null $a
 * @param int|null $b
 * @return int|null  如果返回字符串,则会被转换为int类型
 */
function sum(?int $a, ?int $b): ?int{
    if ($a == null || $b == null) {
        return null;
    }
    return $a + $b;
}

var_dump(sum(1,2));

/**
 * @return void
 *  :void 明确表示该函数没有返回值,可以省略return也可以只写return
 *  该函数返回null
 */
function testReturn(): void
{
    return  ;
}
var_dump(testReturn()); // null

null合并运算符

$a ?? 0 等同于 isset($a) ? $a : 0

$a ?: 0 等同于 $a ? $a : 0

empty: 判断一个变量是否为空(null、false、00、0、’0′、』这类,都会返回true)

isset: 判断一个变量是否设置(值为false、00、0、’0′、』这类,也会返回true)
// 定义之前
print_r($name ?? 'Tom');
// Tom

print_r($name ?: 'Jack');
// Jack
// Undefined variable: name


// 定义之后
$name = '';

print_r($name ?? 'Tom');
// ''

print_r($name ?: 'Jack');
// Jack

$a = 0;
$b = 1;

var_dump($a ?? $b); // int(0)
var_dump(isset($a) ? $a : $b); // int(0)

var_dump($a ?: $b); // int(1)
var_dump($a ? $a : $b); // int(1)

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


太空船操作符用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1。 比较的原则是沿用 PHP 的常规比较规则进行的。

// 整数
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
 
// 浮点数
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
 
// 字符串
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1

匿名类


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

<?php
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) {
        echo $msg;
    }
});
 
var_dump($app->getLogger());
?>

namespace 导入的类

// PHP 7 之前的代码
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
 
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
 
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
 
// PHP 7+ 及更高版本的代码
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};

整数除法函数 intdiv()


<?php
 //新加的函数 intdiv() 用来进行 整数的除法运算。
var_dump(intdiv(10, 3)); //    int(3) 

?>

random_bytes函数


//  一般配合bin2hex()函数使用 
//  bin2hex()把ASCII字符串转换为十六进制值
echo bin2hex(random_bytes(10));

random_bytes() 每次调用都会生成不同内容的二进制字符串,而参数则是二进制的字节长度。直接获取到的二进制数据是乱码格式的,所以一般我们会需要使用 bin2hex() 来将二进制转换成我们可以看懂的十六进制格式字符串。不过由此带来的结果就是我们转换之后的十六进制的字符长度是我们设定的字符长度的 2 倍。这个函数的作用,可以为我们生成安全的用户密码 salt 、 密钥关键字 或者 初始化向量。

原错误内容:random_bytes() 每次调用都会生成不同内容的字符串,而参数则是字符长度的随机字符,在这里我们传递的是 5 ,返回了 10 个字符,可以看出这个参数是字符数量,而返回的其实是字节数量,对应一个字符占用两个字节的返回形式。或者我们就直接记住它返回的就是参数的两倍即可。至于这个函数的作用嘛,可以为我们生成安全的用户密码 salt 、 密钥关键字 或者 初始化向量

数组展开运算

$arrayA = [1, 2, 3];

$arrayB = [4, 5];

$result = [0, ...$arrayA, ...$arrayB, 6 ,7];

// [0, 1, 2, 3, 4, 5, 6, 7]

类常量可见性


class Sky8g
{
    const PUBLIC_CONST_A = 1;
    public const PUBLIC_CONST_B = 2;
    protected const PROTECTED_CONST = 3;
    private const PRIVATE_CONST = 4;
}

多异常捕获处理


<?php
try {
    // some code
} catch (FirstException | SecondException $e) {
    // handle first and second exceptions
}
<?php
//创建四个exception的子类,每个子类中分别有一个可以解决异常问题的方法
class wcexception extends exception{
    function pro(){
        echo "去公厕上厕所<br>";
    }
}
class noexception extends exception{
    function pro(){
        echo "去公司附近吃早餐<br>";
    }
}
class gsexception extends exception{
    function pro(){
        echo "走普通的公路<br>";
    }
}
class luexception extends exception{
    function pro(){
        echo "换上备胎<br>";
    }
}
//定义一个类,包含四种方法对应四种行为,用条件判断如果行为有异常则抛出异常
class dm{
    function gowc($bj){
        if(!$bj){
            throw new wcexception("倒霉催的,厕所坏了<br>");
        }
        echo "上厕所顺利<br>";
    }
    function zc($time){
        if(!$time){
            throw new noexception("没时间吃早餐了<br>");
        }
        echo "早餐很好吃<br>";
    }
    function sgs($xx){
        if(!$xx){
            throw new gsexception("下雪高速封路<br>");
        }
        echo "上高速很顺利<br>";
    }
    function drive($dz){
        if(!$dz)
            throw new luexception("车子爆胎了<br>");
        echo "开车一路顺利<br>";
    }
}
echo "早上起床!<br>";
try{
//创建一个对象,下面调用四个方法分别对应四种可能导致异常的行为
    $ob=new dm();
//上厕所
    $ob->gowc(true);
//吃早餐
    $ob->zc(true);
//上高速
    $ob->sgs(false);
//开车
    $ob->drive(false);
}
//一个try可以对应多个catch
catch(wcexception $e){
    echo $e->getmessage();
    $e->pro();
}
catch(noexception $e){
    echo $e->getmessage();
    $e->pro();
}
catch(gsexception $e){
    echo $e->getmessage();
    $e->pro();
}
//最后一个catch中可以不用exception的子类,这样可以用来捕获漏网之鱼,但不能写出解决方案;
catch(exception $e){
    echo $e->getmessage();
    $e->pro();
}
echo "到公司开始工作<br>";
?>

list()现在支持键名


$data = [
    ["id" => 1, "name" => 'Tom'],
    ["id" => 2, "name" => 'Fred'],
];

// list() style
list("id" => $id1, "name" => $name1) = $data[0];

echo $id1,$name1;//1Tom

支持为负的字符串偏移量


var_dump("abcdef"[-2]);//string (1) "e"

新的对象类型


这种新的对象类型object, 引进了可用于逆变(contravariant)参数输入和协变(covariant)返回任何对象类型。

<?php
function test(object $obj) : object
{
    return new SplQueue();
}
 
test(new StdClass());

类型属性


//类属性现在支持类型声明。
<?php
class User {
    public int $id;
    public string $name;
}
?>

箭头函数


<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);

//短闭包函数
array_map(function (User $user) { 
    return $user->id; 
}, $users)

?>

合并数组新方式


<?php
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>

define() 定义常量数组


define('ANIMALS', [
    'dog',
    'cat',
    'bird'
]);
 
echo ANIMALS[1]; // 输出 "cat

将callback 转闭包

Closure新增了一个静态方法,用于将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');

新增数组函数 array_key_first(), array_key_last()

$array = ['a'=>'1','b'=>'2'];
#php 7.3之前
$firstKey  = key(reset($array));
# php 7.3
$firstKey = array_key_first($array);//a
$lastKey = array_key_last($array);//b

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

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

相关文章

Vue|事件处理

事件处理1. 事件使用1.1 事件绑定1.2 事件参数2. 事件修饰符2.1 阻止默认事件2.2 阻止事件冒泡2.3 事件只允许触发一次2.4 事件捕获2.5 操作当前元素2.6 行为立即执行无需等待回调3. 键盘事件4. 本章小结4.1 事件使用小结4.2 事件修饰符小结4.3 键盘事件小结1. 事件使用 1.1 事…

C++STL剖析(八)—— unordered_set和unordered_multiset的概念和使用

文章目录前言1. unordered_set的介绍和使用&#x1f351; unordered_set的构造&#x1f351; unordered_set的使用&#x1f345; insert&#x1f345; find&#x1f345; erase&#x1f345; size&#x1f345; empty&#x1f345; clear&#x1f345; swap&#x1f345; count…

安全多方计算系列笔记1——前世今生

这一系列笔记参考了绿盟科技研究通讯的安全多方计算文章&#xff0c;及其他。 首先看定义&#xff1a;在不泄露参与方原始输入数据的前提下&#xff0c;允许分布式参与方合作计算任意函数&#xff0c;输出准确的计算结果。 起源 安全多方计算问题及解首先由姚期智&#xff08…

用大白话给你科普,到底什么是 API(应用程序编程接口)?

何为API&#xff1f;如果你在百度百科上搜索&#xff0c;你会得到如下结果&#xff1a;API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组…

Linux 安装Python3

python3 下载地址 python3 下载地址 https://www.python.org/downloads/ 选择自己需要的版本、 此文中选择3.10.9 下载源码压缩包 可下载到本地后上传至Linux服务器也可以复制下载地址 wget https://www.python.org/ftp/python/3.10.9/Python-3.10.9.tgzpython3 安装 yum…

python练习——简化路径

项目场景&#xff1a; 给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 /开头&#xff09;&#xff0c;请你将其转化为更加简洁的规范路径。在 Unix 风格的文件系统中&#xff0c;一个点&#xff08;.&#xff09;表示当前目录本…

新库上线 | CnOpenData中国地方政府债券信息数据

中国地方政府债券信息数据 一、数据简介 地方政府债券 指某一国家中有财政收入的地方政府地方公共机构发行的债券。地方政府债券一般用于交通、通讯、住宅、教育、医院和污水处理系统等地方性公共设施的建设。地方政府债券一般也是以当地政府的税收能力作为还本付息的担保。地…

【电源专题】案例:用电子负载模拟电池测试充电芯片

最近在做有关充电芯片的选型,所以需要测试充电芯片中的很多参数。如涓流充电电流、快速充电电流、截止电流等等。 如下所示为某充电IC充电过程中的电流电压变化曲线。可以看出其中存在多个电流如Ishort/Iterm/Iprechg/Ichgerg等等。电压点也有Vshortz/Vbatlow/Vbatreg等。这些…

VTK- vtkStripper

前言&#xff1a;本博文主要研究接口vtkStripper的实现原理及主要的应用场景&#xff0c;希望对各位小伙伴有所帮助。 描述&#xff1a;vtkStripper是一个过滤器&#xff0c;用于从输入多边形、三角形带和线中生成三角形带和/或折线。输入多边形仅当它们是三角形时才被组装成三…

【Linux】-- 进程信号(处理、内核)

上篇&#xff1a;【Linux】-- 进程信号&#xff08;认识、应用&#xff09;_川入的博客-CSDN博客 目录 信号其他相关常见概念 pending handler block 信号处理的过程 sigset_t sigset_t使用 系统接口 sigpending sigprocmask 捕捉方法 sigaction struct sigactio …

小白入门模拟IC设计,如何快速学习?

众所周知&#xff0c;模拟电路很难学。以最普遍的晶体管来说&#xff0c;我们分析它的时候必须首先分析直流偏置&#xff0c;其次在分析交流输出电压。可以说&#xff0c;确定工作点就是一项相当麻烦的工作&#xff08;实际中来说&#xff09;&#xff0c;晶体管的参数多、参数…

JavaScript 计时事件

JavaScript 计时事件 通过使用 JavaScript&#xff0c;我们有能力做到在一个设定的时间间隔之后来执行代码&#xff0c;而不是在函数被调用后立即执行。我们称之为计时事件。 在 JavaScript 中使用计时事件是很容易的&#xff0c;两个关键方法是: setInterval() - 间隔指定的…

【CNN记录】tensorflow中depth_to_space

功能把depth维的数据移到space上&#xff0c;与spacetodepth刚好是相反的操作&#xff0c;depth对应channel&#xff0c;space对应height和width&#xff0c;而该操作是把depth上的数据分给height和width上&#xff0c;所以对应有一个参数block_size&#xff0c;要求原tensor的…

CSDN竞赛28期参赛体验

1、小Q的鲜榨柠檬汁 1、题目名称&#xff1a;小Q的鲜榨柠檬汁 团建活动是大家所想要的。 小Q给大家准备了鲜橙汁。 现在有n个朋友买回了k瓶饮料&#xff0c;每瓶有l毫升的饮料&#xff0c;同时还买回 了c个柠檬&#xff0c; 每个柠檬可以切成d片&#xff0c;p克盐。 已知每个朋…

Python基础学习笔记 —— 数据结构与算法

数据结构与算法1 数据结构基础1.1 数组1.2 链表1.3 队列1.4 栈1.5 二叉树2 排序算法2.1 冒泡排序2.2 快速排序2.3 &#xff08;简单&#xff09;选择排序2.4 堆排序2.5 &#xff08;直接&#xff09;插入排序3 查找3.1 二分查找1 数据结构基础 本章所需相关基础知识&#xff1a…

第七届蓝桥杯省赛——1有奖猜谜

题目&#xff1a; 小明很喜欢猜谜语。 最近&#xff0c;他被邀请参加了X星球的猜谜活动。 每位选手开始的时候都被发给777个电子币。 规则是&#xff1a;猜对了&#xff0c;手里的电子币数目翻倍&#xff0c; 猜错了&#xff0c;扣除555个电子币, 扣完为止。 小明一共猜了15…

入门深度学习——基于全连接神经网络的手写数字识别案例(python代码实现)

入门深度学习——基于全连接神经网络的手写数字识别案例&#xff08;python代码实现&#xff09; 一、网络构建 1.1 问题导入 如图所示&#xff0c;数字五的图片作为输入&#xff0c;layer01层为输入层&#xff0c;layer02层为隐藏层&#xff0c;找出每列最大值对应索引为输…

云原生周刊 | 开源领导者应该如何应对碎片化挑战?

Linux Fundation 发布了一份关于开源开发中的碎片化问题的报告《实现全球协作&#xff1a;开源领导者如何应对碎片化挑战》&#xff0c;该报告由华为在美国的研发部门 Futurewei 赞助。报告指出&#xff0c;虽然开源社区越来越国际化&#xff0c;但美国对开源共享和开发进行了过…

源码项目中常见设计模式及实现

原文https://mp.weixin.qq.com/s/K8yesHkTCerRhS0HfB0LeA 单例模式 单例模式是指一个类在一个进程中只有一个实例对象&#xff08;但也不一定&#xff0c;比如Spring中的Bean的单例是指在一个容器中是单例的&#xff09; 单例模式创建分为饿汉式和懒汉式&#xff0c;总共大概…

Linux内核驱动开发(一)

Linux内核初探 linux操作系统历史 开发模式 git 分布式管理git clone 获取git push 提交git pull 更新 邮件组 mailing list patch 内核代码组成 Makfile arch 体系系统架构相关 block 块设备 crypto 加密算法 drivers 驱动&#xff08;85%&#xff09; atm 通信bluet…