php7的一些特性
性能提升:PHP7比PHP5.6性能提升了两倍。 Improved performance: PHP 7 is up to twice as fast as PHP 5.6
全面一致的64位支持。 Consistent 64-bit support
以前的许多致命错误,现在改成抛出异常。Many fatal errors are now Exceptions
移除了一些老的不在支持的SAPI(服务器端应用编程端口)和扩展。Removal of old and unsupported SAPIs and extensions
新增了空接合操作符。The null coalescing operator (??)
新增加了结合比较运算符。Combined comparison Operator (<=>)
新增加了函数的返回类型声明。Return Type Declarations
新增加了标量类型声明。Scalar Type Declarations
新增加匿名类。Anonymous Classes
打破一切
PHP7.2的变更:
核心语言变更:
l gettype()对已关闭资源的返回值,从”unkonw type”变为了”resource(closed)”
l 数组对象互转:数组强转为对象时整数键会转换为字符串属性名;对象转数组时,数字字符串属性名会转为整数键。
l 未加引号的字符串常量:对未定义常量的裸字符串引用,现在产生告警,后续会升级成error;
l object不能用作类名;
函数变更:
l 移除了register_globals相关代码;
l Session状态管理更加严格,session_start()、session_regenerate_id()等函数对无效操作会返回正确的布尔值。
废弃功能(7.2已废弃,8.0移除):
l create_function():应改用匿名函数:(function() use(){})
l __autoload():应改用spl_autoload_register()函数。
l assert()已废弃。
移除的扩展:
l Mysql改用PDO或mysqli
l mcrypt改用OpenSSL或Sodium();
l mssql改用PDO_SQLSRV或sqlsrv;
PHP7核心底层优化简述:
1. 引入AST抽象语法树:PHP5.6直接从语法分析生成OPCODE,PHP7先生成AST再编译成OPCODE,解耦语法解析和编译,为后续优化打下基础
2. 内存管理优化:重新设计zval结构,从堆分配改为大部分栈分配,减少内存分配释放开销,内存占用降低30-50%
3. 函数调用优化:优化传参机制,减少调用栈开销,内部函数调用性能提升明显
4. HashTable重构:数组底层HashTable的键值对从单独分配改为连续存储,提升缓存命中率和遍历性能
5. 新增类型声明:标量类型声明(int/float/string/bool)和返回值类型声明,严格模式下编译期类型检查,减少运行时类型判断开销
6. 错误处理重构:引入Throwable接口,把致命错误改成可捕获的Error异常,不再直接崩溃
实际效果:PHP7比PHP5.6性能提升约2倍,内存占用降低约一半。
二、升级兼容性问题及解决:
1. mysql扩展彻底移除:旧mysql_*系列函数全部移除,封装数据库适配层统一改成mysqli或PDO,先封装再逐步替换
2. PHP4风格构造函数废弃:类名同名构造函数废弃,全局替换成__construct()
3. ereg正则扩展移除:ereg_*改成preg_*(PCRE),注意正则语法差异
4. mcrypt扩展在PHP7.1移除:mcrypt_encrypt改成openssl_encrypt,注意算法和填充方式对应
5. 其他:list()不再支持字符串键、foreach内部指针行为变化等,通过单元测试和回归测试覆盖
升级流程:
静态扫描(PHP7 -l语法检查+PHP_CodeSniffer兼容性规则)→测试环境完整回归→按模块灰度上线→错误日志监控→出问题快速回滚。
部署步骤
- 在测试环境完成全部验证
- 备份生产环境代码和数据库
- 在维护窗口期执行升级
- 切换 Web 服务器 PHP 模块
- 验证 phpinfo() 确认版本正确
- 监控应用日志和错误日志
- 如遇问题,准备回滚方案
总结
|
方面 |
关键要点 |
|
升级策略 |
逐级升级(5.6→7.0→7.1→7.2),切勿跳升 |
|
代码兼容 |
关注 gettype()、is_object()、数组/对象转换、废弃函数(create_function、__autoload) |
|
扩展更新 |
mysql→mysqli/PDO,mcrypt→OpenSSL/Sodium,ereg→preg |
|
配置调整 |
更新 php.ini 路径,移除废弃指令,调整 pcre.recursion_limit |
|
性能优化 |
启用 OPcache,合理配置内存和缓存参数 |
|
测试部署 |
渐进测试、独立环境验证、准备回滚方案 |
PHP7底层优化详细解析:
PHP7 的四大底层优化可以概括为一句话:
l AST 解决了编译器的可维护性和优化入口问题;
l 用 zval 重构消灭了标量变量的堆分配和引用计数;
l 用 HashTable 连续存储解决了数组的碎片化和缓存问题;
l 再用类型声明把错误前移。
逐个拆解:每个优化到底解决了什么问题
① AST 抽象语法树 —— 解决 "编译器不可维护、优化无从下手"
PHP5 的问题:词法、语法分析之后直接生成 opcode,中间没有任何表示层。
后果有两个:
编译器代码充满语法糖特判—— 像 foreach、list、array() 这类语法,都需要在生成 opcode 时写一堆特殊逻辑打补丁,代码难维护、难加新语法;
优化无处安放—— 很多优化(常量折叠、冗余消除)需要在 "代码结构" 层面做,而 opcode 是扁平指令流,丢失了语法结构信息,想优化只能针对 opcode 打补丁,非常脆弱。
PHP7 的方案:插入 AST 作为中间层。
语法分析产出的是树形结构,完整保留了 "这段代码是什么表达式、什么语句" 的信息。
编译优化可以在 AST 上安全地做(比如 2 * 3 在编译期直接折叠成 6),编译器的每个环节也各自独立、可单独测试。
收益:编译更快、编译器代码量显著下降、静态分析工具(如 IDE、代码规范工具)有了统一的解析基础 —— 这是 "一次重构,长期受益" 的典型。
② zval 重构 + 栈分配 —— 解决 "内存分配与引用计数开销"
PHP5 的问题:PHP 里每个变量的值都装在一个叫 zval 的结构体里,而这个结构体自带引用计数,且大多在堆上分配。于是:
每写一个变量、传一个参数、返回一个值,都可能触发堆分配;
每次赋值 / 传参都要维护 refcount 的增减(写时复制 COW),这是 PHP5 最著名的性能瓶颈之一;
zval 结构大(64 位下约 24 字节),还要间接寻址一层指针。
PHP7 的方案:重构 zval,把它缩到 16 字节,并做了一次关键的分层 ——
标量(int /double/bool /null)直接内联在 zval 里,不再堆分配、不再有引用计数;
引用计数只保留在真正需要共享的容器上:字符串 zend_string、数组 zend_array、引用;
大量临时变量和局部变量改在执行栈帧上分配,用完即走。
收益:普通标量操作基本实现 "零分配、零引用计数",内存占用整体下降约 50%,执行速度大幅提升。这也解释了为什么 PHP7 在纯计算密集的循环里提速尤其明显。
③ HashTable 重构 —— 解决 "数组底层碎片化、缓存不友好"
PHP5 的问题:PHP 数组的底层是 HashTable,而 HashTable 的每个元素(bucket)是链表节点 + 各自独立 malloc。后果:
插入 N 个元素要分配 N 块小内存,内存碎片严重;
遍历时指针在内存里跳来跳去,CPU 缓存命中率极低—— 现代 CPU 性能很大程度上靠缓存,这在当时是很大的浪费。
PHP7 的方案:把存储模型改成分离式 ——
元素数据连续存放在一块 arData 数组里(按插入顺序),哈希索引单独用一张 uint32 索引表指向数据槽;
整数连续键直接退化为 packed array:不用哈希,直接用数组下标,速度接近 C 数组;
只有真正的字符串键才走哈希计算。
收益:一次大块分配代替 N 次小分配;顺序遍历完全命中缓存;数组遍历、查找、插入普遍快 2–3 倍。因为 PHP 里数组几乎无处不在(请求参数、配置、结果集……),这一项是 PHP7 全局提速的最大功臣之一。
④ 标量类型声明 —— 解决 "类型错误被静默吞掉、接口无契约"
PHP5 的问题:类型提示只支持类、接口、array、callable,不支持 int / float / string / bool。弱类型下,"abc" + 1、把字符串当数字传参这类错误不会被报错,而是被隐式转换静默吞掉,等到线上出 bug 时往往很难定位。
PHP7 的方案:
支持标量类型声明(参数 + 返回值);
引入 declare(strict_types=1) 严格模式:类型不匹配直接抛 TypeError,不做任何隐式转换;
PHP 7.1 补上 ?Type 可空类型和 void 返回类型。
收益(要点要说全):
正确性:错误从 "运行深处" 提前到 "调用边界",立刻暴露;
可维护性:函数签名即文档,接口契约明确;
为优化铺路:类型已知后,引擎在运行时可省去部分动态类型判断 —— 这条在 PHP7 阶段主要是 "铺垫",真正的 JIT 收益要到 PHP8 才兑现,这一点值得明确,不要夸大 PHP7 类型声明的性能收益。


浙公网安备 33010602011771号