| ## テストによると、AST を使用した後、プログラムの全体的な実行時間は約 10% ~ 15% 改善されましたが、メモリ消費量も増加しました。この増加は、大きなファイルの 1 回のコンパイルでは明らかですが、実行中はそうではありません。プロジェクトの実行プロセス全体が非常に深刻な問題です。
また、上記の結果はすべて Opcache を使用していないことにも注意してください。運用環境で Opcache がオンになっている場合、メモリ消費量の増加は大きな問題ではありません。
セマンティックな変更
これが単なる時間の最適化である場合、AST を使用する十分な理由にはならないようです。実際、AST の実装は時間の最適化を考慮したものではなく、構文の問題を解決するために行われています。セマンティクスにおけるいくつかの変更を見てみましょう。
yield には括弧は必要ありません
PHP5 実装では、式コンテキスト (代入式の右側など) で yield を使用する場合、 yield 宣言の両側で括弧を使用する必要があります:
<?php
$result = yield fn(); // 不合法的
$result = (yield fn()); // 合法的
ログイン後にコピー
この動作は、PHP5 の実装制限によるものです。PHP7 では、括弧は必要なくなりました。したがって、次の記述方法も合法です:
<?php
$result = yield;
$result = yield $v;
$result = yield $k => $v;
ログイン後にコピー
もちろん、yield のアプリケーション シナリオに従わなければなりません。
括弧は動作に影響しません
PHP5 では、($foo)['bar'] = 'baz' および $foo['bar'] = 'baz ' 2 つのステートメントの意味は異なります。実は、前者の書き方は違法であり、次のようなエラーが発生します。
<?php
($foo)['bar'] = 'baz';
# PHP Parse error: Syntax error, unexpected '[' on line 1
ログイン後にコピー
しかし、PHP7 では、2 つの書き方は同じ意味になります。
同様に、関数のパラメータが括弧で囲まれている場合、型チェックに問題があります。この問題は PHP7 でも解決されています:
<?php
function func() {
return [];
}
function byRef(array &$a) {
}
byRef((func()));
ログイン後にコピー
上記のコードは、次の場合には警告しません。 PHP5 では byRef が使用されていない限り (func())、PHP7 では func() の両側に括弧があるかどうかに関係なく、次のエラーが発生します。
PHP Strict standards: Only variables should be passed by reference ...
ログイン後にコピー
Changes in list()
list キーワードの動作が大幅に変更されました。リストが変数に値を割り当てる順序 (等号の左右の順序) は、以前は右から左でしたが、現在は左から右です:
<?php
list($array[], $array[], $array[]) = [1, 2, 3];
var_dump($array);
// PHP5: $array = [3, 2, 1]
// PHP7: $array = [1, 2, 3]
# 注意这里的左右的顺序指的是等号左右同时的顺序,
# list($a, $b) = [1, 2] 这种使用中 $a == 1, $b == 2 是没有疑问的。
ログイン後にコピー
上記の変更の理由は、正確には、PHP5 の代入プロセスでは、最初に 3 が配列に入力され、最後に 1 が入力されるためですが、順序が変更されたためです。
同じ変更は次のとおりです:
<?php
$a = [1, 2];
list($a, $b) = $a;
// PHP5: $a = 1, $b = 2
// PHP7: $a = 1, $b = null + "Undefined index 1"
ログイン後にコピー
これは、前の代入プロセスで $b が最初に 2 を取得し、その後 $a の値が 1 になったためです。しかし、今回は $a が最初に変更されます。は 1 になり、配列ではなくなるため、$b は null になります。
list はオフセットごとに 1 回のみアクセスされるようになりました:
<?php
list(list($a, $b)) = $array;
// PHP5:
$b = $array[0][1];
$a = $array[0][0];
// PHP7:
// 会产生一个中间变量,得到 $array[0] 的值
$_tmp = $array[0];
$a = $_tmp[0];
$b = $_tmp[1];
ログイン後にコピー
以前は特定の状況下でのみ空のリスト メンバーがすべて禁止されました:
<?php
list() = $a; // 不合法
list($b, list()) = $a; // 不合法
foreach ($a as list()) // 不合法 (PHP5 中也不合法)
ログイン後にコピー
参照の順序assign
参照割り当ての順序は、PHP5 では右から左でしたが、現在は左から右です。
<?php
$obj = new stdClass;
$obj->a = &$obj->b;
$obj->b = 1;
var_dump($obj);
// PHP5:
object(stdClass)#1 (2) {
["b"] => &int(1)
["a"] => &int(1)
}
// PHP7:
object(stdClass)#1 (2) {
["a"] => &int(1)
["b"] => &int(1)
}
ログイン後にコピー
#clone メソッドは直接呼び出し可能です
これで、$obj->__clone() を直接使用して __clone メソッドを呼び出すことができます。 __clone は、以前は直接呼び出すことが禁止されていた唯一のマジック メソッドでした。以前は、次のようなエラーが発生していました:
Fatal error: Cannot call __clone() method on objects - use 'clone $obj' instead in ...
ログイン後にコピー
変数構文の一貫性
AST もいくつかの問題を解決しました構文の一貫性の問題。これらの問題は別の RFC で提起されました: https://wiki.php.net/rfc/uniform_variable_syntax.
新しい実装では、以前の文法表現の意味は現在とは多少異なります。詳細については、次の表を参照してください:
式 |
PHP5 |
PHP7 |
$foo['bar']['baz'] |
#$ {$foo['bar']['baz']}
|
($$foo)['bar']['baz'] |
$foo->$bar['baz']
| ##$foo->{$bar['baz']}
#($foo->$bar)['baz'] |
| ##$foo->$ bar['baz' ]()
$foo->{$bar['baz']}() |
#($ foo->$bar )['baz']() |
##Foo::$bar['baz']() |
Foo ::{$bar['baz']}()
|
(Foo::$bar)['baz']()
|
全体的に、以前の順序は右から左でしたが、現在は左から右です。また、括弧は動作に影響を与えないという原則に従います。このような複雑な変数の書き方は、実際の開発では注意が必要です。 |
推奨チュートリアル:「PHP7
」