新抽象语法树(AST)给 PHP7 带来的变化

新抽象语法树(AST)给 PHP7 带来的变化
最新回答
江心薄雾起

2021-03-01 09:12:26

PHP7 引入新抽象语法树(AST)后,主要带来了执行过程优化、语义规则调整及语法一致性改进三方面的变化

一、执行过程优化
PHP7 的编译流程从 PHP5 的“词法扫描→语法分析生成 op arrays”调整为“词法扫描→语法分析生成 AST→编译生成 op arrays”。虽然新增了 AST 生成步骤,但实际测试显示,执行时间整体提升 10% 至 15%(小脚本提升 12.5%,中脚本 17.7%,大脚本 16.9%)。这得益于 AST 作为中间表示层,简化了后续编译优化逻辑。不过,内存消耗有所增加(小脚本 +9.5%,中脚本 +26.8%,大脚本 +71.3%),但在完整项目测试中仅增加 5.1%,且生产环境启用 Opcache 后影响可控。

二、语义规则调整

  1. yield 语法简化:PHP5 中表达式上下文使用 yield 需强制加括号(如 ($result = yield fn())),PHP7 允许省略括号,直接写作 $result = yield fn()。
  2. 括号不影响行为:PHP5 中 ($foo)['bar'] 会触发语法错误,PHP7 允许此类写法,且函数参数括号包裹不再导致类型检查失效(如 byRef((func())) 会强制报错)。
  3. list() 赋值顺序反转:PHP5 中 list($a, $b) = [1, 2] 实际从右向左赋值($b 先得 2),PHP7 改为从左向右($a 先得 1)。此外,list 现在禁止空成员(如 list() = $a),且嵌套 list 会生成中间变量(如 list(list($a, $b)) = $array 在 PHP7 中先提取 $array[0])。
  4. 引用赋值顺序反转:PHP5 中 $obj->a = &$obj->b 会先赋值 $b 再关联 $a,导致两者指向同一值;PHP7 改为先关联 $a 再赋值 $b,结果一致但逻辑更清晰。
  5. __clone 方法直接调用:PHP7 允许直接调用 $obj->__clone(),而 PHP5 会报致命错误。

三、语法一致性改进
AST 解决了变量解析顺序的歧义问题。例如,PHP5 中 $$foo['bar']['baz'] 实际解析为 (${${$foo}}['bar']['baz']),而 PHP7 统一为从左向右解析(${$foo['bar']['baz']})。类似地,$foo->$bar['baz'] 在 PHP5 中解析为 ($foo->$bar)['baz'],PHP7 改为 $foo->{$bar['baz']}。这一变化覆盖了动态变量、对象属性、静态调用等场景,强调“括号不影响行为”的原则,减少了开发者因语法歧义导致的错误。

总结:AST 的引入不仅优化了 PHP7 的执行效率,更通过统一语义规则和语法解析逻辑,提升了语言的一致性与可维护性。尽管内存开销略有增加,但在现代硬件环境下,其带来的代码清晰度和性能收益远大于成本。