PHP8 了解新特性

[官方介绍地址](https://www.php.net/releases/8.0/zh.php

php 8.0 五大更新重点

  • 效能提升
  • 语法扩充
  • 弹性强类别
  • 更加严谨
  • 调节内套件与新增函数

性能测试图表

1607602943417.jpg

PHP 8.0 值得关注的改进

  • PHP 8.0 引入了 Just In Time (JIT) 编译器,能够进一步提高 PHP 脚本的执行速度。

  • PHP 8.0 合并了诸多性能优化

  • JSON 支持现在被视为语言的核心部分,始终可用,而不是作为可选模块。

    @1.extension_loaded('json')
    @2.function_exists('json_decode')
    始终返回true

  • 支持 named 参数,因为它们能够指定参数名称而不是其确切顺序。

  • 支持类/属性/函数/方法/参数/常量的结构化元数据的属性(或在其他语言中也称为注释或修饰符)。

  • 支持可以指示多种不同类型的联合类型,这些类型可以用作参数或函数的返回类型。

  • 支持静态返回类型。

  • str_contains()函数是一种检查字符串是否包含在另一个字符串中的简便方法,而不必使用strpos等。与之相似的是新的str_starts_with()和str_ends_with()函数,这些函数很容易解释。

  • 添加了Nullsafe运算符,作为在方法上应用空合并行为的快速简便的方法

什么是 JIT

1、动态编译(dynamic compilation)指的是“在运行时进行编译”;与之相对的是事前编译(ahead-of-time compilation,简称AOT),也叫静态编译(static compilation)。

2、JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。JIT编译是动态编译的一种特例。JIT编译一词后来被泛化,时常与动态编译等价;但要注意广义与狭义的JIT编译所指的区别。
3、自适应动态编译(adaptive dynamic compilation)也是一种动态编译,但它通常执行的时机比JIT编译迟,先让程序“以某种式”先运行起来,收集一些信息之后再做动态编译。这样的编译可以更加优化。

PHP JIT 运作原理

liuchengtu.png

Opcache 扩展可以更快的获取 Opcodes 将其直接转到 Zend VM,则 JIT 让它们完全不使用 Zend VM 即可运行。

跳过 Zend VM 并直接被 CPU 执行。 从理论上说,性能会更好。

查看phpinfo()

1607618000772.jpg
JIT我们配置 php.ini
opcache.jit=1205

opcache.jit_buffer_size=64M
是否在生成机器码点时候使用AVX指令, 需要CPU支持
0: 不使用
1: 使用

####### 寄存器分配策略

0: 不使用寄存器分配
1: 局部(block)域分配
2: 全局(function)域分配

JIT触发策略

0: PHP脚本载入的时候就JIT
1: 当函数第一次被执行时JIT
2: 在一次运行后,JIT调用次数最多的百分之(opcache.prof_threshold * 100)的函数
3: 当函数/方法执行超过N(N和opcache.jit_hot_func相关)次以后JIT
4: 当函数方法的注释中含有@jit的时候对它进行JIT
5: 当一个Trace执行超过N次(和opcache.jit_hot_loop, jit_hot_return等有关)以后JIT
JIT优化策略,数值越大优化力度越大:
0: 不JIT
1: 做opline之间的跳转部分的JIT
2: 内敛opcode handler调用
3: 基于类型推断做函数级别的JIT
4: 基于类型推断,过程调用图做函数级别JIT
5: 基于类型推断,过程调用图做脚本级别的JIT

关于类名调用测试

php 7.4版本
class ImageService
{

    private $src;
    private $image;
    private $imageinfo;
    private $percent = 0.5;

    /** 高清压缩图片
     * @param string $saveName  提供图片名(可不带扩展名,用源图扩展名)用于保存。或不提供文件名直接显示
     */
    public function compressImg($saveName='')
    {

    }
}

###获取类名 方法一
var_dump (ImageService::class);
//打印结果:string(12) "ImageService"

### 获取类名方法二
$obj = new ImageService();
var_dump(get_class ($obj));

//打印结果:string(12) "ImageService"

php8.0 版本
class ImageService
{

    private $src;
    private $image; 

    /** 高清压缩图片
     * @param string $saveName  提供图片名(可不带扩展名,用源图扩展名)用于保存。或不提供文件名直接显示
     */
    public function compressImg($saveName='')
    {

    }
}
 
var_dump($imageObj::class);
//打印结果:string(12) "ImageService"

构造函数可直接定义成员变量

php7.4版本
 ## php7版本
 class MaterialsDao{

     private $name;
     private $pwd;

     public function __construct($name,$pwd)
     {
         $this->name = $name;
         $this->pwd  = $pwd;
     }

 }
 var_dump( new MaterialsDao('admin','!$123123%$'));

 //打印结果
object(MaterialsDao)#1 (2) {
["name":"MaterialsDao":private]=>
  string(5) "admin"
["pwd":"MaterialsDao":private]=>
  string(10) "!$123123%$"
}

php8.0版本 直接定义成员变量

 ## php8版本 构造函数 可直接定义成员变量
 class  MaterialsPHP8Dao{

    public function __construct(private $name,private $pwd)
    {

    }

}

var_dump( new MaterialsPHP8Dao('admin','!$123123%$'));

 //打印结果
 object(MaterialsPHP8Dao)#1 (2) {
  ["name":"MaterialsPHP8Dao":private]=>
  string(5) "admin"
  ["pwd":"MaterialsPHP8Dao":private]=>
  string(10) "!$123123%$"
}

字符串的处理

1.判断字符串中是否存在某个字符

php 7.4 版本

$url = "https://www.php.net/releases/8.0/zh.php";

//原来方式@1. strstr
 $domain = strstr($url,'http');
 echo $domain; 

//原来方式@2. strpos

if(strpos($url,'http')!==false || strpos($url,'https')!==false){
     echo "包含http或https";
}else{
     echo "不包含http";
}

php8.0 版本 新增str_contains函数

$url = "https://www.php.net/releases/8.0/zh.php";
if(str_contains($url,"http")){
    echo "包含http或https";
}else{
    echo "不包含http";
}

2.判断字符串是否以开头 或 以结尾

php7.4版本

$str = ":测试一下喽";
if (':' ==  substr($str, 0, 1)) {
    echo "ok";
}else{
    echo "no";
}

php8.0版本 新增 str_stars_with:开始函数 str_ends_with:结束函数

  if(str_starts_with($str,":测试")){
    echo "以':测试'开头";
  }else{
    echo  "否";
  }


  if(str_ends_with($str,"喽")){
    echo "以'喽'结束";
   }else{
    echo  "否";
   }  

3.新的关键字:match, 这个关键字的作用跟switch有点类似。

php7.4版本 switch

switch ($input) {
    case "true":
        $result = 1;
    break;
    case "false":
        $result = 0;
    break;
    case "null":
        $result = NULL;
    break;
}

php 8.0 版本 新关键词match

$result = match($input) {
        "true" => 1,
        "false" => 0,
        "null" => NULL,
};

###多个值
$result = match($input) {
    "true", "on" => 1,
    "false", "off" => 0,
    "null", "empty", "NaN" => NULL,
};

4. 串联优先级

## 串联优先级 测试
$a = 100;
$b = 200;

echo '两数之和:' . $a + $b . PHP_EOL;

// PHP7.* 执行顺序是: ('两数之和:' . $a) + $b .PHP_EOL; 
## 打印输出 200

// PHP8执行顺序是: '两数之和:' . ($a + $b) . PHP_EOL;
## 打印输出 300

5. 联合类型 索引

// 参数是联合类型
function paramsUnionType(array|bool $data) {
    var_dump($data);
}

// 参数为数组
paramsUnionType(['a', 'd', 'e']);

// 参数为布尔型
paramsUnionType(false);


// 返回值是联合类型
function retUnionType($data) : array|bool|string {
    return $data;
}

// 返回值为数组类型
var_dump(retUnionType(['b', 'a', 1]));
// 返回值为布尔类型
var_dump(retUnionType(true));
// 返回值为字符串类型
var_dump(retUnionType('new1024kb'));
 
// 参数和返回值都是联合类型
function unionType(array|bool $data): bool|array {
    return $data;
}

// 数组类型
var_dump(unionType(['a', 'f', 'q']));
// 布尔类型
var_dump(unionType(true));
// 整型(会被转换成bool型 true)
var_dump(unionType(127867));

6.fdiv 函数 允许除数为0

// 除数为0
var_dump(fdiv(2, 0));
var_dump(fdiv(1, 3));
var_dump(fdiv(1, 2));
// intdiv() 对结果取整
// fmod() 返回余数
返回结果:
float(INF)
float(0.3333333333333333)
float(0.5)

get_debug_type和gettype() 区别

$arr = [1, 2, 3];

echo '数组类型' . PHP_EOL;
var_dump('get_debug_type(): '. get_debug_type($arr));
var_dump('gettype(): ' . gettype($arr));

$str = 'new1024kb';

echo '字符串类型' . PHP_EOL;
var_dump('get_debug_type(): ' . get_debug_type($str));
var_dump('gettype(): ' . gettype($str));

echo PHP_EOL;



$i = 1024;

echo '整型' . PHP_EOL;
var_dump('get_debug_type(): ' . get_debug_type($i));
var_dump('gettype(): ' . gettype($i));

echo PHP_EOL;

$str = 10.24;

echo '字符串类型' . PHP_EOL;
var_dump('get_debug_type(): ' . get_debug_type($str));
var_dump('gettype(): ' . gettype($str));

echo PHP_EOL;
 
$b = false;

echo '布尔型' . PHP_EOL;
var_dump('get_debug_type(): ' . get_debug_type($b));
var_dump('gettype(): ' . gettype($b));

echo PHP_EOL;
 

class Type{}
$type = new Type();

echo '对象' . PHP_EOL;
var_dump('get_debug_type(): ' . get_debug_type($type));
var_dump('gettype(): ' . gettype($type));


运行结果:

函数 参数int型 参数string型 参数布尔bool型 参数数组array型 对象浮点型 实例化
- int string bool array float 实例化
get_debug_type int string bool array float 类名
gettype integer string boolean array double object

7. php8 新增参数跳过 参数与顺序无关,且是自描述的。

属性


function named_params($a, $b, $c = 0, $d = 0) {
    echo $a."-".$b."-".$c."-".$d;
}
echo "function: ";
named_params(1, 2,d:20 );

##打印结果: 1-2-0-20%   

8. NULLsafe

php7.4

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

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

php8.0

$country = $session?->user?->getAddress()?->country;

9. PHP 8新特性之Attributes 注释

php7.4 版本

/**
 * @param $where
 * @param string $field
 * @return array
 */
function getOne($where, $field='*'){

    return  [];
}

$ref = new ReflectionFunction("getOne");
var_dump ( $ref->getDocComment());

## 打印结果
string(6) "author"
array(2) {
  [0]=>
  string(6) "123123"
  [1]=>
  string(44) "https://stitcher.io/blog/attributes-in-php-8"
} 

php8.0


$ref01 = new ReflectionFunction("getOneById");

var_dump($ref01->getAttributes("Params")[0]->getName());
var_dump($ref01->getAttributes("Params")[0]->getArguments());

var_dump($ref01->getAttributes("See")[0]->getName());
var_dump($ref01->getAttributes("See")[0]->getArguments());

string(3) "see"
array(2) {
  [0]=>
  string(6) "123123"
  [1]=>
  string(44) "https://stitcher.io/blog/attributes-in-php-8"
}

#[Params("name", "pwd"),author("123123","https://stitcher.io/blog/attributes-in-php-8")]
function getOneByName($name,$pwd){
    return boolval (1);
}

$ref01 = new ReflectionFunction("getOneByName");

var_dump($ref01->getAttributes("Params")[0]->getName());
var_dump($ref01->getAttributes("Params")[0]->getArguments());

string(6) "Params"
array(2) {
  [0]=>
  string(4) "name"
  [1]=>
  string(3) "pwd"
}


var_dump($ref01->getAttributes("author")[0]->getName());
var_dump($ref01->getAttributes("author")[0]->getArguments());

string(6) "author"
array(2) {
  [0]=>
  string(6) "123123"
  [1]=>
  string(44) "https://stitcher.io/blog/attributes-in-php-8"
}


总结

  • 新语法开始面向其他设计語言
  • PHP 开始活用强型别写发的特性
  • PHP 正在一步一步的要求严谨
  • JIT 目前在 PHP 8.0 能提升的情境有限
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容