php7.4分享

php7.3, php7.4相关介绍

[toc]

mac本地 php7.4源码安装

  • 可能提前需要安装 re2c, bison

brew install bison
brew install re2c

  • FFI 默认关闭,需要主动开启

YACC=/usr/local/opt/bison@3.5/bin/bison ./configure --with-ffi --enable-opcache [option...]

docker安装

wget -O dnmp.zip https://pan.yidian-inc.com/index.php/s/iU0MjWdpN3UKG0V
unzip dnmp.zip && cd dnmp
docker-composer up -d

新特性

更加灵活的heredoc和nowdoc

  • 支持闭合标记符的缩进
  • 不再强制闭合标记符的换行;
$libc = FFI::cdef(
    <<<EOF
        int argInt(int n);
        
    EOF, __DIR__ . '/libclang/lib/cstr.so');

var_dump($libc->argInt(33));

类属性支持类型定义,并严格限制其使用

当给一个int型的属性赋值一个string类型,会引发fatal error

# Fatal error: Uncaught TypeError: Typed property User::$id must be int, string used
# TypeError: Typed property User::$id must be int, string used
class User {
    public int $id;
    public string $name;
}
$user = new User();
$user->id = 'test';

支持调用时参数的尾随逗号

只是在调用函数时可用,函数定义是不允许的
提高了代码的可读性, 在需要频繁加参数的场景中,可以减少忘记加逗号而引起的错误。
也便于调试

var_dump(
    $result,
    $dbData,
);

json_decode新增错误标识JSON_THROW_ON_ERROR

当json解析错误时,会抛异常JsonException。
而在php7.2中,解析失败会返回null,需要再通过json_last_error来判断是否解析错误。

try {
    $json = json_doecode('{', false, 512, JSON_THROW_ON_ERROR);

} catch (\JsonException $exception) {
    echo $exception->getMessage();
}

null合并运算符

    $var ??= 'test string';
    // 等同于
    if(!isset($var)) {
        $var = 'test string';
    }

支持数组内解

Spread 运算符应该比 array_merge 拥有更好的性能。
这不仅仅是 Spread 运算符是一个语法结构,而 array_merge 是一个方法。还是在编译时,优化了高效率的常量数组

新函数 array_key_first,array_key_last

// 新函数 array_key_first 返回数组的第一个key
$firstKey = array_key_first($array);
// ==等同于
reset($array);  // 重置内部指针到第一个位置
$firstKey = key($array);    // key指向当前内部指针所指向的位置

// 新函数 array_key_last 返回数组的最后一个key
$endKey = array_key_last($array);
// ==等同于
end($array);    // 重置内部指针到最后一个位置
$endKey = key($array);

其他参考

https://www.php.net/manual/en/migration73.new-features.php
https://www.php.net/manual/en/migration74.new-features.php

向后不兼容修改

heredoc和nowdoc的结束符不能在内部有定义

# 在php7.2可正常执行并输出 test\r\nEOF, 在php7.3及其以后,会抛异常
# Parse error: Invalid body indentation level (expecting an indentation level of at least 4) 
$test = <<<EOF
test
    EOF 
EOF;

数组方式访问null,bool,int,float,res等类型($null['key'])会引发一个notice

Notice: Trying to access array offset on value of type null

其他参考:

https://www.php.net/manual/en/migration73.incompatible.php
https://www.php.net/manual/en/migration74.incompatible.php

废弃功能

大小写不敏感的常量

将 TRUE 作为第三个参数传递给 define() 将会导致一个废弃警告
Deprecated: define(): Declaration of case-insensitive constants is deprecated

array_key_exists()用于对象中已被废弃

应该使用isset() or property_exists()

Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead

大括号获取数组元素已被弃用

Use arr['idx'] instead of arr{'idx'}.

Deprecated: Array and string offset access syntax with curly braces is deprecated

其他参考:

https://www.php.net/manual/en/migration73.deprecated.php
https://www.php.net/manual/en/migration74.deprecated.php

opcache.preload 新特性介绍

opcode&opcache基础介绍

graph LR; 
G[request] -.-> A[.php] -.-> B[词法分析] -.-> C[语法分析] -.-> D[生成opcode] -.-> E[执行opcode] -.-> F[response]

每一次请求PHP脚本都会执行一遍以上步骤,如果PHP源代码没有变化,那么Opcode也不会变化,显然没有必要每次都重新生成Opcode

由此,我们可以缓存opcode,缓存后的执行流程如下:

graph LR;

A[request] -.-> B[.php] -.-> H{获取opcache}
H -.-> |yes|C[执行opcode] -.-> G[response]
H -.-> |no|D[词法分析] -.-> E[语法分析] -.-> F[生成opcode] -.-> C[执行opcode]
F -.-> I[生成opcache]

opcache的目的就是避免重复编译,减少CPU和内存的消耗

opcache的不足

  • 从缓存中获取文件的成本。
  • 检查源文件是否被修改
  • 单个文件缓存,无法得知不同文件类的依赖关系,仍然需要重新连接类依赖项。

preload原理

官方文档指出, 该项提案受 类共享内存的启发(“Class Data Sharing” technology designed for Java HotSpot VM. )
在运行任何应用程序代码之前 - 我们可以将一组PHP文件加载到内存中 - 并使其内容“permanently available”到该服务器将服务的所有后续请求。这些文件中定义的所有函数和类将可用于开箱即用的请求,与内部实体完全相同(例如strlen()方法或Exception类)。

preload使用限制

  • class, funciton, trait, interface能够进行预加载(在满足依赖的情况下)
  • 全局变量,define, const,无法被预加载
  • 类变量定义未使用的会有preload warning警告
  • 预加载只加载文件,不执行文件,因此动态生成的一切无法被预加载。
  • 一个类具有未预加载的依赖项,则其本身也不能被预加载

由于不同的应用程序(或同一应用程序的不同版本)在不同的文件中可能有相同的类/函数名,如果类的一个版本是预加载的——它将防止加载在不同文件中定义的该类的任何其他版本。

preload使用

修改php.ini配置文件:

# 在服务器启动的时候,就会去加载该路径的文件,进行预加载
opcache.preload=/var/www/html/website/vendor/preload.php

# php-fpm指定的user
opcache.preload_user=www-data 

cmposer预加载支持

https://github.com/composer/composer/issues/7777

composer g require ayesh/composer-preload
cd website/
# edit composer.json
mkdir -p webroot/vendor
composer preload
php-fpm restart

composer.json

{
    "extra": {
        "preload": {
            "paths": [
                "base",
                "dao",
                "util",
                "cron",
                "yaconf"
            ],
            "exclude": [
                "vendor"
            ],
            "extensions": ["php", "ini"],
            "no-status-check": false
        }
    }
}

更多细节:https://github.com/Ayesh/Composer-Preload

通过 var_dump(opcache_get_status()['scripts']) 可以查看预加载的文件

Composer-preload 注意点

  • 初始化预加载后,如果有在预加载文件之类的一些请求,也会继续被预加载。
  • 代码存在已被废弃的功能,生成预加载文件后会导致fpm无法启动。

使用性能总结

FFI 新特性介绍

FFI(Foreign Function Interface)允许以一种语言编写的代码调用另一种语言的代码,而libffi库提供了最底层的、与架构相关的、完整的FFI。libffi的作用就相当于编译器,它为多种调用规则提供了一系列高级语言编程接口,然后通过相应接口完成函数调用,底层会根据对应的规则,完成数据准备,生成相应的汇编指令代码。

项目使用

扩展部分

  • yaconf 官方github未提供php74的版本, 有第三方版本可以使用。第三方github
  • protobuf 官方github未提供php74的版本, 第三方版本编译通过但仍会报错。ISSUES地址

代码兼容

其他

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

推荐阅读更多精彩内容